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());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章