SpringBoot如何優雅的校驗參數

NO IMAGE

原文地址原文地址

前言

做web開發有一點很煩人就是要校驗參數,基本上每個接口都要對參數進行校驗,比如一些格式校驗 非空校驗都是必不可少的。如果參數比較少的話還是容易 處理的一但參數比較多了的話代碼中就會出現大量的IF ELSE就比如下面這樣:

SpringBoot如何優雅的校驗參數

這個例子只是校驗了一下空參數。如果需要驗證郵箱格式和手機號格式校驗的話代碼會更多,所以介紹一下validator通過註解的方式進行校驗參數。

什麼是Validator

Bean Validation是Java定義的一套基於註解的數據校驗規範,目前已經從JSR 303的1.0版本升級到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成於2017.08),已經經歷了三個版本 。在SpringBoot中已經集成在 starter-web中,所以無需在添加其他依賴。

SpringBoot如何優雅的校驗參數

註解介紹

validator內置註解

註解詳細信息
@Null被註釋的元素必須為 null
@NotNull被註釋的元素必須不為 null
@AssertTrue被註釋的元素必須為 true
@AssertFalse被註釋的元素必須為 false
@Min(value)被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@Max(value)被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@DecimalMin(value)被註釋的元素必須是一個數字,其值必須大於等於指定的最小值
@DecimalMax(value)被註釋的元素必須是一個數字,其值必須小於等於指定的最大值
@Size(max, min)被註釋的元素的大小必須在指定的範圍內
@Digits (integer, fraction)被註釋的元素必須是一個數字,其值必須在可接受的範圍內
@Past被註釋的元素必須是一個過去的日期
@Future被註釋的元素必須是一個將來的日期
@Pattern(value)被註釋的元素必須符合指定的正則表達式

Hibernate Validator 附加的 constraint

註解詳細信息
@Email被註釋的元素必須是電子郵箱地址
@Length被註釋的字符串的大小必須在指定的範圍內
@NotEmpty被註釋的字符串的必須非空
@Range被註釋的元素必須在合適的範圍內
@NotBlank驗證字符串非null,且長度必須大於0

注意

  • @NotNull 適用於任何類型被註解的元素必須不能與NULL
  • @NotEmpty 適用於String Map或者數組不能為Null且長度必須大於0
  • @NotBlank 只能用於String上面 不能為null,調用trim()後,長度必須大於0

使用

使用起來也非常簡單,下面略過創建項目

GITHUB地址:

模擬用戶註冊封裝了一個UserDTO

當提交數據的時候如果使用以前的做法就是IF ELSE判斷參數使用validator則是需要增加註解即可。

例如非空校驗:

SpringBoot如何優雅的校驗參數

然後需要在controller方法體添加@Validated不加@Validated校驗會不起作用

SpringBoot如何優雅的校驗參數

然後請求一下請求接口,把Email參數設置為空

參數:

{
"userName":"luomengsun",
"mobileNo":"11111111111",
"sex":1,
"age":21,
"email":""
}

返回結果:

SpringBoot如何優雅的校驗參數

後臺拋出異常

SpringBoot如何優雅的校驗參數

這樣是能校驗成功,但是有個問題就是返回參數並不理想,前端也並不容易處理返回參數,所以我們添加一下全局異常處理,然後添加一下全局統一返回參數這樣比較規範。

添加全局異常

創建一個GlobalExceptionHandler類,在類上方添加@RestControllerAdvice註解然後添加以下代碼:

    /**
* 方法參數校驗
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ReturnVO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
return new ReturnVO().error(e.getBindingResult().getFieldError().getDefaultMessage());
}

此方法主要捕捉MethodArgumentNotValidException異常然後對異常結果進行封裝,如果需要在自行添加其他異常處理。

添加完之後我們在看一下運行結果,調用接口返回:

{
"code": "9999",
"desc": "郵箱不能為空",
"data": null
}

OK 已經對異常進行處理。

校驗格式

如果想要校驗郵箱格式或者手機號的話也非常簡單。

校驗郵箱

    /**
* 郵箱
*/
@NotBlank(message = "郵箱不能為空")
@NotNull(message = "郵箱不能為空")
@Email(message = "郵箱格式錯誤")
private String email;

使用正則校驗手機號

校驗手機號使用正則進行校驗,然後限制了一下位數

    /**
* 手機號
*/
@NotNull(message = "手機號不能為空")
@NotBlank(message = "手機號不能為空")
@Pattern(regexp ="^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手機號格式有誤")
@Max(value = 11,message = "手機號只能為{max}位")
@Min(value = 11,message = "手機號只能為{min}位")
private String mobileNo;

查看一下運行結果

傳入參數:

{
"userName":"luomengsun",
"mobileNo":"111111a",
"sex":1,
"age":21,
"email":"1212121"
}

返回結果:

{
"code": "9999",
"desc": "郵箱格式錯誤",
"data": null
}

這裡不再驗證手機號的例子

自定義註解

上面的註解只有這麼多,如果有特殊校驗的參數我們可以使用Validator自定義註解進行校驗

首先創建一個IdCard註解類

@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {
String message() default "身份證號碼不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

在UserDTO中添加@IdCard註解即可驗證,在運行時觸發,本文不對自定義註解做過多的解釋,下篇文章介紹自定義註解

  • message 提示信息
  • groups 分組
  • payload 針對於Bean

然後添加IdCardValidator 主要進行驗證邏輯

SpringBoot如何優雅的校驗參數

上面調用了is18ByteIdCardComplex方法,傳入參數就是手機號,驗證身份證規則自行百度:seenoevil:

然後使用

    @NotNull(message = "身份證號不能為空")
@IdCard(message = "身份證不合法")
private String IdCardNumber;

分組

就比如上面我們定義的UserDTO中的參數如果要服用的話怎麼辦?

在重新定義一個類然後裡面的參數要重新添加註解?

Validator提供了分組方法完美瞭解決DTO服用問題

現在我們註冊的接口修改一下規則,只有用戶名不能為空其他參數都不進行校驗

先創建分組的接口

public interface Create  extends Default {
}

我們只需要在註解加入分組參數即可例如:

  /**
* 用戶名
*/
@NotBlank(message = "用戶姓名不能為空",groups = Create.class)
@NotNull(message = "用戶姓名不能為空",groups = Create.class)
private String userName;
@NotBlank(message = "郵箱不能為空",groups = Update.class)
@NotNull(message = "郵箱不能為空",groups = Update.class)
@Email(message = "郵箱格式錯誤",groups = Update.class)
private String email;

然後在修改Controller在@Validated中傳入Create.class

    @PostMapping("/user")
public ReturnVO userRegistra(@RequestBody @Validated(Create.class) UserDTO userDTO){
ReturnVO returnVO = userService.userRegistra(userDTO);
return returnVO ;
}

然後調用傳入參數:

{
"userName":"",
}

返回參數:

{
"code": "9999",
"desc": "用戶姓名不能為空",
"data": null
}

OK 現在只對Create的進行校驗,而Updata組的不校驗,如果需要複用DTO的話可以使用分組校驗

校驗單個參數

在開發的時候一定遇到過單個參數的情況,在參數前面加上註解即可

    @PostMapping("/get")
public ReturnVO getUserInfo(@RequestParam("userId") @NotNull(message = "用戶ID不能為空") String userId){
return new ReturnVO().success();
}

然後在Controller類上面增加@Validated註解,注意不是增加在參數前面。

SpringBoot如何優雅的校驗參數

相關文章

一文搞懂V8引擎的垃圾回收

精讀《正交的React組件》

如何封裝一個flutter的多語言plugin

我在真實項目中使用了AST大法!