- 概述
在日常应用中,存在大量需要针对输入数据进行验证的应用场景,例如字符串的大小,ip地址验证,email格式验证等等各类情况。
值得开心的是Spring Boot将这类场景进行了集成抽象,提供一个完整而且灵活的机制简化开发者在进行相关操作时的重复工作量。
- Maven引用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
springboot需要引入spring-boot-starter-validation(使用Hibernate Validator 框架提供验证功能) 依赖进行参数校验,由于本项目中已经引入了spring-boot-starter-web 依赖(包含spring-boot-starter-validation依赖),就不需要重复引用了。
@Valid是使用Hibernate validation的时候使用
@Validated是只用Spring Validator校验机制使用
说明:java的JSR303声明了@Valid这类接口,而Hibernate-validator对其进行了实现
@Validation对@Valid进行了二次封装,在使用上并没有区别,但在分组、注解位置、嵌套验证等功能上有所不同,这里主要就这几种情况进行说明。
- 基本注解介绍
@NotEmpty:作用在String、collection、map、数组上,不能为null,size > 0
@NotBlank: 只能用于String,不能为null,也不可以是" ",即trim()后长度大于0
@NotNull:作用于任何类型,不能为null,可以为空
@AssertTrue:必须为true
@AssertFalse:必须为false
@Min(value):必须为一个数字,且值大于等于指定的值
@Max(value):必须为一个数字,且值小于等于指定的值
@Size(max,min):限制参数大小范围
@Future:必须是一个将来的日期
@Past:必须是一个过去的日期
@Pattern(value):指定正则
- 注解的使用范围
@Validated:用在类型、方法和方法参数上。但不能用于成员属性(field)
代码详情
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
Class<?>[] value() default {};
}
@Valid:可以用在方法、构造函数、方法参数和成员属性(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;
- 基本使用
- 作用在参数上
@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: 个数必须在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.统一的异常处理类来处理不同的错误:
@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();
}
}
网友评论