SpringBoot检验注解
@Null 限制只能为null。
@NotNull 限制必须不为null。
@NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0。
@NotBlank 只作用于字符串类型,字符串不为空,并且trim()后不为空串。
@AssertFalse 限制必须为false。
@AssertTrue 限制必须为true。
@DecimalMax(value) 限制必须为一个不大于指定值的数字。
@DecimalMin(value) 限制必须为一个不小于指定值的数字。
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction。
@Future 限制必须是一个将来的日期。
@Past 验证注解的元素值(日期类型)比当前时间早。
@Max(value) 限制必须为一个不大于指定值的数字。
@Min(value) 限制必须为一个不小于指定值的数字。
@Pattern(value) 限制必须符合指定的正则表达式。
@Size(max,min) 限制字符长度必须在min到max之间。
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式。
注意:
@NotNull 适用于任何类型被注解的元素必须不能与NULL。
@NotEmpty 适用于String Map或者数组不能为Null且长度必须大于0。
@NotBlank 只能用于String上面 不能为null,调用trim()后,长度必须大于0。
单个参数校验
复制
@RestController
@RequestMapping("validator/")
@Validated
public class ValidatorController {
@GetMapping("/add")
public String add(@NotNull(message = "address不能为空") String address) {
return "检验通过";
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
请求:127.0.0.1:8080/validator/add?address=中国。
返回:检验通过。
请求:127.0.0.1:8080/validator/add。
返回:address不能为空。
说明:在进行单个参数校验时,一定要在Controler类上加@Validated注解,否则校验不会生效。
实体类参数校验
实体User类:
复制
public class User {
@NotBlank(message = "请输入名称")
@Length(message = "名称不能超过个 {max} 字符", max = 5)
public String name;
@NotNull(message = "请输入年龄")
@Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
public Integer age;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
controller类:
复制
@RestController
@RequestMapping("validator/")
public class ValidatorController {
@PostMapping("/add")
public String addUser(@RequestBody @Valid User user, BindingResult bindingResult) {
//查看所有字段是否验证通过
if (bindingResult.hasErrors()) {
//返回第一条错误信息
return bindingResult.getAllErrors().get(0).getDefaultMessage();
}
return "检验通过";
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
执行如下:
说明:如果采用BindingResult方式来存储异常结果,就必须自己来处理异常。即接口中有BindingResult参数,就必须使用要有上方7,8,9行代码进行异常处理,否则程序会正常执行。
统一异常管理
实体User类,同上。controller类如下:
复制
@RequestMapping("validator/")
public class ValidatorController {
@PostMapping("/add")
public String addUser(@Valid @RequestBody User user) {
return "检验通过";
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
执行结果:
这里没有采用BindingResult来存储异常,程序在这里会报错。可以在这个地方增加统一异常管理。通过报错信息可以知道需要对MethodArgumentNotValidException进行管理,代码如下:
复制
@RestControllerAdvice
public class ValidatedExceptionHander {
@ExceptionHandler(MethodArgumentNotValidException.class)
public String MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
String exceptionInfo = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return exceptionInfo;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
再次执行:
使用spring boot校验器
检验器代码:
复制
@Component
public class ValidatorUtil implements ApplicationContextAware {
// 通过Spring获得校验器
private static Validator validator;
@Override
public void setApplicationContext(ApplicationContext applicationContext){
Validator validatorBean = applicationContext.getBean(Validator.class);
setValidator(validatorBean);
}
public static void setValidator(Validator validatorBean){
if (validatorBean instanceof LocalValidatorFactoryBean) {
validator = ((LocalValidatorFactoryBean) validatorBean).getValidator();
} else if (validatorBean instanceof SpringValidatorAdapter) {
validator = validatorBean.unwrap(Validator.class);
} else {
validator = validatorBean;
}
}
public static <T> void validate(T object){
Set<ConstraintViolation<T>> violationSet = validator.validate(object);
for (ConstraintViolation<T> violation : violationSet) {
throw new ValidationException(violation.getMessage());
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
统一异常管理:
复制
@RestControllerAdvice
public class ValidatedExceptionHander {
@ExceptionHandler(value = ValidationException.class)
public String ValidationException(ValidationException exception) {
return exception.getMessage();
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
controller类如下:
复制
@RestController
@RequestMapping("validator/")
public class ValidatorController {
@PostMapping("/add")
public String addUser(@RequestBody User user) {
ValidatorUtil.validate(user);
return "检验通过";
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
执行如下:
说明:这么做的好处是可以自由的对实体进行检验,与以上方式相比较为灵活。
分组校验
同一个实体在不同的操作中的校验方式是不同的,这就要用到分组校验。比如实体User在新增操作时,id是没有的,但是在更新操作时id又必须存在。通过下面例子来讲解一下是如何实现的。
实体user:
复制
public class User {
@NotNull(message = "id不能为空", groups = {User.UpdateGroup.class})
@Null(message = "id必须为空", groups = {User.InsertGroup.class})
public Integer id;
@NotBlank(message = "请输入名称")
@Length(message = "名称不能超过个 {max} 字符", max = 5)
public String name;
@NotNull(message = "请输入年龄")
@Range(message = "年龄范围为 {min} 到 {max} 之间", min = 1, max = 100)
public Integer age;
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public interface InsertGroup{}
public interface UpdateGroup{}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
统一异常:
复制
@RestControllerAdvice
public class ValidatedExceptionHander {
@ExceptionHandler(MethodArgumentNotValidException.class)
public String MethodArgumentNotValidHandler(MethodArgumentNotValidException exception) {
String exceptionInfo = exception.getBindingResult().getAllErrors().get(0).getDefaultMessage();
return exceptionInfo;
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
controller类:
复制
@RestController
@RequestMapping("validator/")
public class ValidatorController {
@GetMapping("/update")
public String updateUser(@Validated(User.UpdateGroup.class) @RequestBody User user) {
return "更新成功";
}
@GetMapping("/insert")
public String insertUser(@Validated(User.InsertGroup.class) @RequestBody User user) {
return "保存成功";
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
执行如下:
@Validated和@Valid区别
@Validated 对@Valid 进行了二次封装,但在分组、注解位置、嵌套验证等功能上有所不同。
不同点 | @Valid | @Validated |
来源 | 是Hibernate validation 的 校验注解 | 是 Spring Validator 的校验注解,是 Hibernate validation 基础上的增加版 |
注解位置 | 用在 构造函数、方法、方法参数 和 成员属性上 | 用在 类、方法和方法参数上。但不能用于成员属性 |
嵌套验证 | 用在级联对象的成员属性上面 | 不支持 |
分组 | 无此功能 | 提供分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制 |