springboot2.3版本以后需要引入validation依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>2.2.8.RELEASE</version>
</dependency>
或者使用:
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.17.Final</version>
</dependency>
一、 @Valid和@Validaed区别
检验入参是否符合规范,使用@Validated或者@Valid在基本验证功能上一致,两者的不同之处在于
@Validated不能用在成员属性(字段)上,@Valid不支持分组
@Validaed是Spring Validation验证框架提供的,@Valid是javax提供的标准JSR-303规范
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上,支持分组
@Valid:可以用在方法、成员属性(字段)上、构造函数、方法参数和类型
二、校验注解(用在入参实体类属性):
- 空和非空检查注解
@Null 带注解的元素必须是null,接受任何类型
@NotEmpty 带注解的元素不能为null或空。支持的类型:String、Collection、Map、Array
@NotNull 带注解的元素必须不为null,接受任何类型
@NotBlank 带注解的元素不能是null,并且必须包含至少一个非空白字符。接受String类型
- Boolean值检查
@AssertTrue 带注解的元素必须为true。支持的类型是boolean 和 Boolean}。null元素被认为有效
@AssertFalse 带注解的元素必须为false。支持的类型是boolean 和 Boolean。null元素被认为有效
- 长度检查
@Size(max,min) 带注解的元素大小必须在指定的边界之间(包括在内)。支持类型:String、Collection、Map、Array,null元素被认为有效
@Max(value) 带注解的元素必须是一个数值,其值必须小于或等于指定的最大值。支持类型BigDecimal、BigInteger、byte、short、int、long还有他们各自的包装类,null元素被认为有效
@Min(value) 带注解的元素必须是一个数值,其值必须大于或等于指定的最小值。支持类型:BigDecimal、BigInteger、byte、short、int、long还有他们各自的包装类,null元素被认为有效
@DecimalMax(value)其值必须小于或等于指定的字符串数字
@DecimalMin(value)其值必须大于或等于指定的字符串数字
@Digits(integer=,fraction=) 验证是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。
@Negative 被注解的元素必须是一个严格的负数(即0被认为是一个无效值)。
@NegativeOrZero 被注解的元素必须是一个负数或者为0
@Positive 被注解的元素必须是一个严格的正数(即0被认为是一个无效值)。
@PositiveOrZero 被注解的元素必须是一个正数或者为0
- 日期检查
@Past 带注解的元素必须是过去的时刻,日期或时间。
@PastOrPresent 带注解的元素必须是过去或现在的时刻、日期或时间
@Future 带注解的元素必须是一个瞬间、日期或将来的时间。
@FutureOrPresent 带注解的元素必须是当前或将来的即时、日期或时间
- 其他检查
@Pattern(value) 带注解的String必须匹配指定的正则表达式。正则表达式遵循Java正则表达式约定
@Email() 字符串必须是格式良好的电子邮件地址。准确的语义构成一个有效电子邮件地址留给Bean验证提供商。接受String。
三、嵌套校验
如果 User 类中增加一个 Order 类的属性,而 Order 中的属性也需要校验,就用到递归校验了,只要在相应属性上增加@Valid注解即可实现(对于集合同样适用)
public class User {
@NotBlank
private String name;
@Valid
private Order order;
}
public class Order {
@NotNull
private Long id;
@NotBlank
private String itemName;
}
四、分组校验:
分组校验是指在不同的场景下对一个参数进行不同的校验,比如对用户进行新建和修改操作,新建允许name字段为空,修改则不允许
定义一个分组接口
public interface Group1 {
}
public interface Group2 {
}
在实体类上加分组接口
public class User {
@NotBlank(message = "用户名不能为空!", groups = {Group1.class})
private String name;
}
在Controller方法的参数上加上@Validated注解并添加分组类
@RestController
@RequestMapping("/test/validated")
public class TestController {
@PostMapping("/insert")
public User validatedDemo1(@Validated @RequestBody User user){
return userRepository.save(user);
}
@PostMapping("/update")
public User validatedDemo2(@Validated(Group1.class) @RequestBody User user){
return userRepository.update(user);
}
}
五、全局异常处理
如果不对异常进行处理,Spring框架会抛出异常信息。
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final String BAD_REQUEST_MSG = "参数检验失败";
//处理 form data方式调用接口校验失败抛出的异常
@ExceptionHandler(BindException.class)
public ResultInfo bindExceptionHandler(BindException e) {
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
List<String> collect = fieldErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toList());
return ResultInfo.success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
}
// 处理 json 请求体调用接口校验失败抛出的异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResultInfo methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
List<String> collect = fieldErrors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toList());
return ResultInfo.success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
}
// 处理单个参数校验失败抛出的异常
@ExceptionHandler(ConstraintViolationException.class)
public ResultInfo constraintViolationExceptionHandler(ConstraintViolationException e) {
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
List<String> collect = constraintViolations.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());
return ResultInfo.success(HttpStatus.BAD_REQUEST.value(), BAD_REQUEST_MSG, collect);
}
}
网友评论