一、JSR 303 是什么?
JSR-303 是 Java EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是hibernate Validator。
二、JSR 303 能做什么?
- 1.JSR 303 用于对java Bean 中的字段的值进行验证,使得基本的验证逻辑可以从业务代码中脱离出来。
- 2.是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。
三、都有些什么验证?
hibernate Validator对JSR303做了比较全面的实现,springboot 自带,并且还额外提供了一些实现,如下:
Constraint | 说明 | 作用类型 |
---|---|---|
@Null | 被注释的元素必须为 null | 引用类型 |
@NotNull | 被注释的元素必须不为 null | 引用类型 |
@AssertTrue | 被注释的元素必须为 true | boolean |
@AssertFalse | 被注释的元素必须为 false | boolean |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 | byte、short、int、long及对应的包装类型以及BigDecimal、BigInteger |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | byte、short、int、long及对应的包装类型以及BigDecimal、BigInteger |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 | byte、short、int、long及对应的包装类型以及BigDecimal、BigInteger、String |
@DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | byte、short、int、long及对应的包装类型以及BigDecimal、BigInteger、String |
@Size(max, min) | 被注释的元素的大小必须在指定的范围内 | String、Collection、Map和数组 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 | byte、short、int、long及各自的包装类型以及BigDecimal、BigInteger、String |
@Past | 被注释的元素必须是一个过去的日期 | java.util.Date,java.util.Calendar |
@Future | 被注释的元素必须是一个将来的日期 | java.util.Date,java.util.Calendar |
@Pattern(regex=) | 被注释的元素必须符合指定的正则表达式 | String |
@Valid | 被注释的元素需要递归验证 | 引用对象 |
以下是hibernate Validator新增的
Constraint | 说明 | 作用类型 |
---|---|---|
被注释的元素必须是电子邮箱地址 | String | |
@Length(min=下限, max=上限) | 被注释的字符串的大小必须在指定的范围内 | String |
@NotEmpty | 被注释的元素的必须非空并且size大于0 | String、Collection、Map和数组 |
@NotBlank | 被注释的元素必须不为空且不能全部为’ '(空字符串) | String |
@Range(min=最小值, max=最大值) | 被注释的元素必须在合适的范围内 | byte、short、int、long及各自的包装类型以及BigDecimal、BigInteger、String |
注意:@Valid 和 BindingResult 是一一对应的,如果有多个@Valid,那么每个@Valid后面跟着的BindingResult就是这个@Valid的验证结果,顺序不能乱
四、参考示例操作
方法上添加 @Validated
public Result<Void> insert(@RequestBody @Validated TradeSpuCategoryDto tradeSpuCategoryDto) {
传递参数的实体类中 ,如有嵌套验证使用 @Valid
@NotNull(message = "不能为空")
private String attrName;
@Min(value = 1, message = "不能小于1")
private Integer stockWarning;
@DecimalMin(value="0.00",message = "必须大于等于0")
private BigDecimal commission;
// 嵌套验证
@Valid
private List<SkuVerifyDto> skuVerifyDto;
五、@Validated和 @Valid 的区别
- @Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
- @Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
六、需要的依赖(springboot 自带,无需添加)
<!--jsr 303-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.1.0.Final</version>
</dependency>
<!-- hibernate validator-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.0.Final</version>
</dependency>
七、参数异常返回前端 (注意此异常为受检查异常)
会检查前端传递的参数返回对应的错误信息
/**
* 异常处理类/ 全局异常 /自定义异常
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler extends BaseService {
/**
* TODO 全局异常 --> 受检查异常。可以理解为错误,必须要开发者解决以后才能编译通过,这里JSR 303 为受检查异常
* 解决的方法有两种1:throw到上层,2,try-catch处理。
*
* @param e
* @author ws
* @mail [email protected]
* @date 2020/2/9 0009 10:06
*/
@ExceptionHandler(Exception.class)
public Result<String> exceptionHandler(Exception e) {
StringBuffer url = request.getRequestURL();
log.info("###全局受检查异常###,url:{} --> ERROR:{}", url, e.getMessage());
if (e instanceof MethodArgumentNotValidException) {
// JSR 303 为参数验证错误
return new Result<String>(ResultType.SYSTEM_VALID_ILLEGAL_PARAM, e.getMessage());
} else if (e instanceof MissingServletRequestParameterException) {
// 未传递Parameter 参数验证错误,一般方法测试指定了 @Parameter 的参数未传递
return new Result<String>(ResultType.SYSTEM_PARAMETER_ILLEGAL_PARAM, e.getMessage());
}
// Result 为返回数据对象,
// ResultType.SYSTEM_ERROR=返回的code和msg,
// e.getMessage() =当前错误信息
return new Result<String>(ResultType.SYSTEM_ERROR, e.getMessage());
}
}