Spring Validation 验证框架与 javax 都提供了对数据的校验功能,一个是 @Validated(JSR-303变种),一个是 @Valid(标准JSR-303)。
添加validation依赖:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-validationartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.10version>
dependency>
通过 LocalValidatorFactoryBean 类可以看到,校验的提示信息可以写在 ValidationMessages.properties 文件中:
user.name.notnull=用户名不能为空
user.password.notnull=密码不能为空
user.email.notnull=邮箱不能为空
user.email.pattern=邮箱格式不正确
编写User实体类:
@Data
public class User {
@NotNull(message = "{user.name.notnull}")
private String name;
@NotNull(message = "{user.password.notnull}")
private String password;
@Email(message = "{user.email.pattern}")
@NotNull(message = "{user.email.notnull}")
private String email;
}
这里只是测试,就直接写Controller接口,使用 @Validated 注解:
@RestController
@RequestMapping("/valid")
public class DemoController {
@PostMapping("/addUser")
public String addUser(@Validated @RequestBody User user){
String res = "用户名:"+user.getName()+",密码:"+user.getPassword()+",邮箱:"+user.getEmail();
return res;
}
}
如果校验的结果不对,默认会返回400,这里我们通过ResponseEntityExceptionHandler自定义异常处理类,使得我们的接口能返回错误信息:
@RestControllerAdvice
public class ValidatorHandlerAdvice extends ResponseEntityExceptionHandler {
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status,
WebRequest request) {
List<String> errors = new ArrayList<>();
List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
for(ObjectError error : allErrors){
errors.add(error.getDefaultMessage());
}
return new ResponseEntity(errors, status);
}
}
使用 Postman 进行测试:
某一个实体中定义了很多的校验规则,但有时候我们并不需要这么多的校验规则,这个时候就可以使用分组校验。
创建两个分组接口:
public interface UserValidationGroup1 {
}
public interface UserValidationGroup2 {
}
修改User实体类:
@Data
public class User {
@NotNull(message = "{user.name.notnull}",groups = {UserValidationGroup1.class, UserValidationGroup2.class})
private String name;
@NotNull(message = "{user.password.notnull},groups = {UserValidationGroup1.class, UserValidationGroup2.class}")
private String password;
@Email(message = "{user.email.pattern},groups = UserValidationGroup1.class")
@NotNull(message = "{user.email.notnull},groups = UserValidationGroup2.class")
private String email;
}
接口指定分组:
@RestController
@RequestMapping("/valid")
public class DemoController {
@PostMapping("/addUser")
public String addUser(@Validated(UserValidationGroup2.class) @RequestBody User user){
String res = "用户名:"+user.getName()+",密码:"+user.getPassword()+",邮箱:"+user.getEmail();
return res;
}
}
@Validated指定UserValidationGroup2分组,不会校验邮箱格式:
注解 | 作用 |
---|---|
@Null | 被注释的元素必须为 null |
@NotNull | 被注释的元素必须不为 null |
@AssertTrue | 被注释的元素必须为 true |
@AssertFalse | 被注释的元素必须为 false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max=, min=) | 被注释的元素的大小必须在指定的范围内 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
@Pattern(regex=,flag=) | 被注释的元素必须符合指定的正则表达式 |
@NotBlank(message =) | 验证字符串非null,且长度必须大于0 |
被注释的元素必须是电子邮箱地址 | |
@Length(min=,max=) | 被注释的字符串的大小必须在指定的范围内 |
@NotEmpty | 被注释的字符串的必须非空 |
@Range(min=,max=,message=) | 被注释的元素必须在合适的范围内 |
有诸如一下形式:
class Person{
@NotNull
private String name;
...
}
class Room{
@NotNull
@Valid //只能使用@Valid
List<Person> personList;
}
这样才能对 personList 中的 Person 进行校验。
@Validated 或者@Valid 在基本验证功能上没有太多区别,需要注意的是:
分组:@Validated 有分组功能,而 @Valid 还没有。
作用地方:@Validated 可以用在类型、方法和方法参数,不能用在成员属性上;而 @Valid 可以用在方法、构造函数、方法参数和成员属性上。