- 概述
在日常應用中,存在大量需要針對輸入數(shù)據進行驗證的應用場景,例如字符串的大小,ip地址驗證,email格式驗證等等各類情況。
值得開心的是Spring Boot將這類場景進行了集成抽象,提供一個完整而且靈活的機制簡化開發(fā)者在進行相關操作時的重復工作量。
- Maven引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
springboot需要引入spring-boot-starter-validation(使用Hibernate Validator 框架提供驗證功能) 依賴進行參數(shù)校驗,由于本項目中已經引入了spring-boot-starter-web 依賴(包含spring-boot-starter-validation依賴),就不需要重復引用了。
@Valid是使用Hibernate validation的時候使用
@Validated是只用Spring Validator校驗機制使用
說明:java的JSR303聲明了@Valid這類接口,而Hibernate-validator對其進行了實現(xiàn)
@Validation對@Valid進行了二次封裝,在使用上并沒有區(qū)別,但在分組、注解位置、嵌套驗證等功能上有所不同,這里主要就這幾種情況進行說明。
- 基本注解介紹
@NotEmpty:作用在String、collection、map、數(shù)組上,不能為null,size > 0
@NotBlank: 只能用于String,不能為null,也不可以是" ",即trim()后長度大于0
@NotNull:作用于任何類型,不能為null,可以為空
@AssertTrue:必須為true
@AssertFalse:必須為false
@Min(value):必須為一個數(shù)字,且值大于等于指定的值
@Max(value):必須為一個數(shù)字,且值小于等于指定的值
@Size(max,min):限制參數(shù)大小范圍
@Future:必須是一個將來的日期
@Past:必須是一個過去的日期
@Pattern(value):指定正則
- 注解的使用范圍
@Validated:用在類型、方法和方法參數(shù)上。但不能用于成員屬性(field)
代碼詳情
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
Class<?>[] value() default {};
}
@Valid:可以用在方法、構造函數(shù)、方法參數(shù)和成員屬性(field)上
代碼詳情
@Target({ METHOD, FIELD, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface Valid {
}
注意事項:
- 在Spring MVC應用中,允許使用上述各類的@Valid 和@Validated注解去驗證@RequestParam和@PathVariable中定義的各類params。(兩個可以混用)但是使用@Validated來修飾整個類,表示其中方法需要在method這個級別使用validation邏輯進行驗證。
- 嵌套校驗:一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@Valid,才能驗證待驗證對象中的成員屬性,這里不能使用@Validated。
@Valid
@NotNull(message = "任課老師不能為空")
@Size(min = 1, message = "至少有一個老師")
private List<TeacherBean> teacherBeans;
- 基本使用
- 作用在參數(shù)上
@RestController
@Validated
public class xxxxController {
……
@RequestMapping("/validationStudent")
public Object validationStudent(@Validated @NotEmpty @Size(min = 2, max = 45,message = "xxxx") @RequestParam("name") String name,
@RequestParam("sex") boolean sex,
@Valid @Max(value = 100,message = "xxxx") @Min(value=0,message = "xxx") @RequestParam("age") int age,
@Valid @NotEmpty @Length(min = 12, max = 12,message = "長度不合法") @RequestParam("stuno") String stuno) {
Student student = new Student();
student.setAge(age);
student.setName(name);
student.setSex(sex);
student.setStuno(stuno);
return student;
}
異常信息類似:javax.validation.ConstraintViolationException: validationStudent.name: 個數(shù)必須在2和45之間, validationStudent.stuno: 長度不合法
- 作用在jsonbean上
public class TeacherBean {
@NotEmpty(message = "老師姓名不能為空")
private String teacherName;
@Min(value = 1, message = "學科類型從1開始計算")
private int type;
}
public class StudentBean implements Serializable{
@NotBlank(message = "用戶名不能為空")
private String name;
@Min(value = 18, message = "年齡不能小于18歲")
private Integer age;
@Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤")
private String phoneNum;
@Email(message = "郵箱格式錯誤")
private String email;
@MyConstraint
private String className;
@Valid
@NotNull(message = "任課老師不能為空")
@Size(min = 1, message = "至少有一個老師")
private List<TeacherBean> teacherBeans;
}
@RestController
public class CheckController {
@PostMapping("stu")
public String addStu(@Valid @RequestBody StudentBean studentBean){
return "add student success";
}
}
異常信息類似:
MethodArgumentNotValidException:xxxx
如果缺少@RequestBody 注解會報錯:BindException:xxx
3.統(tǒng)一的異常處理類來處理不同的錯誤:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Object ExceptionHandler(Exception ex) {
ex.printStackTrace();
return "Exception: " + ex.getMessage();
}
@ExceptionHandler(ConstraintViolationException.class)
public Object ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
ex.printStackTrace();
return "ConstraintViolationException: " + ex.getMessage();
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
ex.printStackTrace();
return "MethodArgumentNotValidException: " + ex.getMessage();
}
@ExceptionHandler(BindException.class)
public Object BindExceptionHandler(BindException ex) {
ex.printStackTrace();
return "BindException: " + ex.getMessage();
}
}