springboot 使用 JSR 303 进行参数验证

一、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 说明 作用类型
@Email 被注释的元素必须是电子邮箱地址 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());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章