SpringBoot中優雅處理參數驗證,到底發生了什麼?

一、為什麼使用 @Valid 來驗證參數

在平常通過 Spring 框架寫代碼時候,會經常寫接口類,相信大家對該類的寫法非常熟悉。在寫接口時經常要寫效驗請求參數邏輯,這時候我們會常用做法是寫大量的 if 與 ifelse 類似這樣的代碼來做判斷,如下:

SpringBoot中優雅處理參數驗證,到底發生了什麼?


這樣的代碼如果按正常代碼邏輯來說,是沒有什麼問題的,不過按優雅來說,簡直糟糕透了。不僅不優雅,而且如果存在大量的驗證邏輯,這會使代碼看起來亂糟糟,大大降低代碼可讀性,那麼有沒有更好的方法能夠簡化這個過程呢?答案當然是有,推薦的是使用 @Valid註解來幫助我們簡化驗證邏輯。

二、@Valid 註解的作用

註解 @Valid 的主要作用是用於數據效驗,可以在定義的實體中的屬性上,添加不同的註解來完成不同的校驗規則,而在接口類中的接收數據參數中添加 @valid 註解,這時你的實體將會開啟一個校驗的功能。

三、@Valid 的相關注解

下面是 @Valid 相關的註解,在實體類中不同的屬性上添加不同的註解,就能實現不同數據的效驗功能。

SpringBoot中優雅處理參數驗證,到底發生了什麼?


SpringBoot中優雅處理參數驗證,到底發生了什麼?

四、使用 @Valid 進行參數效驗步驟

整個過程如下圖所示,用戶訪問接口,然後進行參數效驗,因為 @Valid 不支持平面的參數效驗(直接寫在參數中字段的效驗)所以基於 GET 請求的參數還是按照原先方式進行效驗,而 POST 則可以以實體對象為參數,可以使用 @Valid 方式進行效驗。如果效驗通過,則進入業務邏輯,否則拋出異常,交由全局異常處理器進行處理。

SpringBoot中優雅處理參數驗證,到底發生了什麼?

1、實體類中添加 @Valid 相關注解

使用 @Valid 相關注解非常簡單,只需要在參數的實體類中屬性上面添加如 @NotBlank、 @Max、 @Min 等註解來對該字段進限制,如下:

User:

SpringBoot中優雅處理參數驗證,到底發生了什麼?

如果是嵌套的實體對象,則需要在最外層屬性上添加 @Valid 註解:

User:

SpringBoot中優雅處理參數驗證,到底發生了什麼?

UserInfo:

SpringBoot中優雅處理參數驗證,到底發生了什麼?

2、接口類中添加 @Valid 註解

在 Controller 類中添加接口, POST 方法中接收設置了 @Valid 相關注解的實體對象,然後在參數中添加 @Valid 註解來開啟效驗功能,需要注意的是, @Valid 對 Get 請求中接收的平面參數請求無效,稍微略顯遺憾。

SpringBoot中優雅處理參數驗證,到底發生了什麼?

3、全局異常處理類中處理 @Valid 拋出的異常

最後,我們寫一個全局異常處理類,然後對接口中拋出的異常進行處理,而 @Valid 配合 Spring 會拋出 MethodArgumentNotValidException 異常,這裡我們需要對該異常進行處理即可。

SpringBoot中優雅處理參數驗證,到底發生了什麼?

五、SpringBoot 中使用 @Valid 示例

1、Maven 引入相關依賴

Maven 引入 SpringBoot 相關依賴,這裡引入了 Lombok 包來簡化開發過程。

<code>/<code>
<code><project>/<code>
<code>xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">/<code>
<code><modelversion>4.0.0/<modelversion>/<code>
<code><parent>/<code>
<code><groupid>org.springframework.boot/<groupid>/<code>
<code><artifactid>spring-boot-starter-parent/<artifactid>/<code>
<code><version>2.2.1.RELEASE/<version>/<code>
<code>
<code><groupid>com.aspire/<groupid>/<code>
<code><artifactid>springboot-valid-demo/<artifactid>/<code>
<code><version>0.0.1-SNAPSHOT/<version>/<code>
<code><name>springboot-valid-demo/<name>/<code>
<code><description>@valid demo/<description>/<code>
<code><properties>/<code>
<code><java.version>1.8/<java.version>/<code>
<code>
<code><dependencies>/<code>
<code><dependency>/<code>
<code><groupid>org.springframework.boot/<groupid>/<code>
<code><artifactid>spring-boot-starter-web/<artifactid>/<code>
<code>
<code><dependency>/<code>
<code><groupid>org.projectlombok/<groupid>/<code>
<code><artifactid>lombok/<artifactid>/<code>
<code><optional>true/<optional>/<code>
<code>
<code>
<code><build>/<code>
<code><plugins>/<code>
<code><plugin>/<code>
<code><groupid>org.springframework.boot/<groupid>/<code>
<code><artifactid>spring-boot-maven-plugin/<artifactid>/<code>
<code>
<code>
<code>
<code>

2、自定義個異常類

自定義個異常類,方便我們處理 GET 請求(GET 請求參數中一般是沒有實體對象的,所以不能使用 @Valid),當請求驗證失敗時,手動拋出自定義異常,交由全局異常處理。

SpringBoot中優雅處理參數驗證,到底發生了什麼?


3、自定義響應枚舉類

定義一個返回信息的枚舉類,方便我們快速響應信息,不必每次都寫返回消息和響應碼。

SpringBoot中優雅處理參數驗證,到底發生了什麼?

4、自定義響應對象類

創建用於返回調用方的響應信息的實體類。

SpringBoot中優雅處理參數驗證,到底發生了什麼?

5、自定義實體類中添加 @Valid 相關注解

下面將創建用於 POST 方法接收參數的實體對象,裡面添加 @Valid 相關驗證註解,並在註解中添加出錯時的響應消息。

User

SpringBoot中優雅處理參數驗證,到底發生了什麼?

UserInfo

SpringBoot中優雅處理參數驗證,到底發生了什麼?

6、Controller 中添加 @Valid 註解

接口類中添加 GET 和 POST 方法的兩個接口用於測試,其中 POST 方法以上面創建的 Uer 實體對象接收參數,並使用 @Valid,而 GET 請求一般接收參數較少,所以使用正常判斷邏輯進行參數效驗。

<code>import club . myd1q. valid. entity .ResponseResult;/<code>
<code>import club . myd1q.valid.entity.User;/<code>
<code>import club . myd1q. valid. enums . ResultEnum;/<code>
<code>import club . myd1q. valid. exception. ParamaErrorException;/<code>
<code>import org. springframework . validation . annotation .Validated;/<code>
<code>import org. springframework . web. bind . annotation.* ;/<code>
<code>import javax . validation.Valid;/<code>
<code>@RestController/<code>
<code>public class TestController {/<code>
<code>/**/<code>
<code>獲取用戶信息/<code>
<code>@param username/<code>
<code>姓名/<code>
<code>@return ResponseResult/<code>
<code>/**/<code>
<code>@Validated/<code>
<code>@GetMapping(" /user/{username }")/<code>
<code>public ResponseResult findUserInfo (@PathVariable String username) {/<code>
<code>if (username == null | |/<code>
<code>””. equals(username)) {/<code>
<code>throw new Par amaErrorException("username不能為空”);/<code>
<code>}/<code>
<code>return new ResponseResult (ResultEnum . SUCCESS);/<code>
<code>}/<code>
<code>/**/<code>
<code>新增用戶/<code> 
<code>@param user/<code>
<code>用戶信息/<code>
<code>@return ResponseResult /<code>
<code>**//<code>
<code>@PostMapping(" /user")/<code>
<code>public ResponseResult addUserInfo(@Valid @RequestBody User user) {/<code>
<code>return new ResponseResult (ResultEnum. SUCCESS);/<code>
<code>}/<code>
<code>}/<code>

7、全局異常處理

這裡創建一個全局異常處理類,方便統一處理異常錯誤信息。裡面添加了不同異常處理的方法,專門用於處理接口中拋出的異常信。

8、啟動類

SpringBoot中優雅處理參數驗證,到底發生了什麼?

9、示例測試

下面將針對上面示例中設置的兩種接口進行測試,分別來驗證參數效驗功能。

|| - 測試接口 /user/{username}

使用 GET 方法請求地址 http://localhost:8080/user?username=test 時,返回信息:

SpringBoot中優雅處理參數驗證,到底發生了什麼?

|| - 測試接口 /user

(1)、使用 POST 方法發起請求,首先進行不加 JSON 請求體來對 http://localhost:8080/user 地址進行請求,返回信息:

<code>{    "code": 1001,    "msg": "參數體不能為空"}/<code>

(2)、輸入部分參數進行測試。

  • 請求內容:
<code>{ "username":"test",  "password":"123"}/<code>
  • 返回信息:
<code>{    "code": 1001,     "msg": "userinfo不能為空"}/<code>

(3)、輸入完整參數,且設置 age > 18 時,進行測試。

<code>{ "username":"111",   "password":"sa",     "userInfo":{    "age":19,        "gender":"男"                 }}/<code>
  • 返回信息:
<code>{    "code": 1001,     "msg": "不能超過18歲"}/<code>

可以看到在執行 POST 請求,也能正常按我們全局異常處理器中的設置處理異常信息,且提示信息為我們設置在實體類中的 Message。


分享到:


相關文章: