作web開發有一點很煩人就是要校驗參數,基本上每一個接口都要對參數進行校驗,好比一些格式校驗 非空校驗都是必不可少的。若是參數比較少的話仍是容易 處理的一但參數比較多了的話代碼中就會出現大量的IF ELSE
就好比下面這樣:前端
這個例子只是校驗了一下空參數。若是須要驗證郵箱格式和手機號格式校驗的話代碼會更多,因此介紹一下validator
經過註解的方式進行校驗參數。git
Bean Validation是Java定義的一套基於註解的數據校驗規範,目前已經從JSR 303的1.0版本升級到JSR 349的1.1版本,再到JSR 380的2.0版本(2.0完成於2017.08),已經經歷了三個版本 。在SpringBoot
中已經集成在 starter-web
中,因此無需在添加其餘依賴。web
註解 |
詳細信息 |
---|---|
@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) |
被註釋的元素必須符合指定的正則表達式 |
註解 | 詳細信息 |
---|---|
@Email |
被註釋的元素必須是電子郵箱地址 |
@Length |
被註釋的字符串的大小必須在指定的範圍內 |
@NotEmpty |
被註釋的字符串的必須非空 |
@Range |
被註釋的元素必須在合適的範圍內 |
@NotBlank |
驗證字符串非null,且長度必須大於0 |
注意:正則表達式
使用起來也很是簡單,下面略過建立項目數組
GITHUB地址:app
模擬用戶註冊封裝了一個UserDTO
spa
當提交數據的時候若是使用之前的作法就是IF ELSE
判斷參數使用validator
則是須要增長註解便可。3d
例如非空校驗:code
而後須要在controller
方法體添加@Validated
不加@Validated
校驗會不起做用
而後請求一下請求接口,把Email參數設置爲空
參數:
{
"userName":"luomengsun",
"mobileNo":"11111111111",
"sex":1,
"age":21,
"email":""
}複製代碼
返回結果:
後臺拋出異常
這樣是能校驗成功,可是有個問題就是返回參數並不理想,前端也並不容易處理返回參數,因此咱們添加一下全局異常處理,而後添加一下全局統一返回參數這樣比較規範。
建立一個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
註解便可驗證,在運行時觸發,本文不對自定義註解作過多的解釋,下篇文章介紹自定義註解
而後添加IdCardValidator
主要進行驗證邏輯
上面調用了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
註解,注意不是增長在參數前面。