<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot使用@Valid注解+Exception全局處理器優(yōu)雅處理參數(shù)驗(yàn)證

          共 6423字,需瀏覽 13分鐘

           ·

          2022-06-24 15:30

          目錄

          一、為什么使用 @Valid 來驗(yàn)證參數(shù)

          二、@Valid 注解的作用

          三、@Valid 的相關(guān)注解

          四、使用 @Valid 進(jìn)行參數(shù)校驗(yàn)步驟

          • 實(shí)體類中添加 @Valid 相關(guān)注解

          • 接口類中添加 @Valid 注解

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

          五、SpringBoot 中使用 @Valid 示例

          • Maven 引入相關(guān)依賴

          • 自定義個(gè)異常類

          • 自定義響應(yīng)枚舉類

          • 自定義響應(yīng)對(duì)象類

          • 自定義實(shí)體類中添加 @Valid 相關(guān)注解

          • Controller 中添加 @Valid 注解

          • 全局異常處理

          • 啟動(dòng)類

          • 示例測試

          相關(guān)地址:

          Spring Servlet 文檔:
          https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/web/servlet示例項(xiàng)目 Github:https://github.com/my-dlq/blog-example/tree/master/springboot/springboot-filter-example系統(tǒng)環(huán)境:

          Jdk 版本:jdk 8

          SpringBoot 版本:2.2.1.RELEASE

          一、為什么使用 @Valid 來驗(yàn)證參數(shù)

          在平常通過 Spring 框架寫代碼時(shí)候,會(huì)經(jīng)常寫接口類,相信大家對(duì)該類的寫法非常熟悉。在寫接口時(shí)經(jīng)常要寫效驗(yàn)請(qǐng)求參數(shù)邏輯,這時(shí)候我們會(huì)常用做法是寫大量的 if 與 if else 類似這樣的代碼來做判斷,如下:

          這樣的代碼如果按正常代碼邏輯來說,是沒有什么問題的,不過按優(yōu)雅來說,簡直糟糕透了。不僅不優(yōu)雅,而且如果存在大量的驗(yàn)證邏輯,這會(huì)使代碼看起來亂糟糟,大大降低代碼可讀性,那么有沒有更好的方法能夠簡化這個(gè)過程呢?

          答案當(dāng)然是有,推薦的是使用 @Valid 注解來幫助我們簡化驗(yàn)證邏輯。

          二、@Valid 注解的作用

          注解 @Valid 的主要作用是用于數(shù)據(jù)校驗(yàn),可以在定義的實(shí)體中的屬性上,添加不同的注解來完成不同的校驗(yàn)規(guī)則,而在接口類中的接收數(shù)據(jù)參數(shù)中添加 @valid 注解,這時(shí)你的實(shí)體將會(huì)開啟一個(gè)校驗(yàn)的功能。

          三、@Valid 的相關(guān)注解

          下面是 @Valid 相關(guān)的注解,在實(shí)體類中不同的屬性上添加不同的注解,就能實(shí)現(xiàn)不同數(shù)據(jù)的效驗(yàn)功能。

          四、使用 @Valid 進(jìn)行參數(shù)校驗(yàn)步驟

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

          1、實(shí)體類中添加 @Valid 相關(guān)注解

          使用 @Valid 相關(guān)注解非常簡單,只需要在參數(shù)的實(shí)體類中屬性上面添加如 @NotBlank、@Max、@Min 等注解來對(duì)該字段進(jìn)限制,如下:

          User:

          如果是嵌套的實(shí)體對(duì)象,則需要在最外層屬性上添加 @Valid 注解:

          User:

          UserInfo:

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

          在 Controller 類中添加接口,POST 方法中接收設(shè)置了 @Valid 相關(guān)注解的實(shí)體對(duì)象,然后在參數(shù)中添加 @Valid 注解來開啟效驗(yàn)功能,需要注意的是, @Valid 對(duì) Get 請(qǐng)求中接收的平面參數(shù)請(qǐng)求無效,稍微略顯遺憾。

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

          最后,我們寫一個(gè)全局異常處理類,然后對(duì)接口中拋出的異常進(jìn)行處理,而 @Valid 配合 Spring 會(huì)拋出
          MethodArgumentNotValidException 異常,這里我們需要對(duì)該異常進(jìn)行處理即可。

          五、SpringBoot 中使用 @Valid 示例

          1、Maven 引入相關(guān)依賴

          Maven 引入 SpringBoot 相關(guān)依賴,這里引入了 Lombok 包來簡化開發(fā)過程。

          2、自定義個(gè)異常類

          自定義個(gè)異常類,方便我們處理 GET 請(qǐng)求(GET 請(qǐng)求參數(shù)中一般是沒有實(shí)體對(duì)象的,所以不能使用 @Valid),當(dāng)請(qǐng)求驗(yàn)證失敗時(shí),手動(dòng)拋出自定義異常,交由全局異常處理。

          3、自定義響應(yīng)枚舉類

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

          4、自定義響應(yīng)對(duì)象類

          創(chuàng)建用于返回調(diào)用方的響應(yīng)信息的實(shí)體類。

          5、自定義實(shí)體類中添加 @Valid 相關(guān)注解

          下面將創(chuàng)建用于 POST 方法接收參數(shù)的實(shí)體對(duì)象,里面添加 @Valid 相關(guān)驗(yàn)證注解,并在注解中添加出錯(cuò)時(shí)的響應(yīng)消息。

          User

          UserInfo

          6、Controller 中添加 @Valid 注解

          接口類中添加 GET 和 POST 方法的兩個(gè)接口用于測試,其中 POST 方法以上面創(chuàng)建的 Uer 實(shí)體對(duì)象接收參數(shù),并使用 @Valid,而 GET 請(qǐng)求一般接收參數(shù)較少,所以使用正常判斷邏輯進(jìn)行參數(shù)效驗(yàn)。

          7、全局異常處理

          這里創(chuàng)建一個(gè)全局異常處理類,方便統(tǒng)一處理異常錯(cuò)誤信息。里面添加了不同異常處理的方法,專門用于處理接口中拋出的異常信。

          import club.mydlq.valid.entity.ResponseResult;import club.mydlq.valid.enums.ResultEnum;import club.mydlq.valid.exception.ParamaErrorException;import lombok.extern.slf4j.Slf4j;import org.springframework.http.HttpStatus;import org.springframework.http.converter.HttpMessageNotReadableException;import org.springframework.util.StringUtils;import org.springframework.validation.BindingResult;import org.springframework.validation.FieldError;import org.springframework.validation.ObjectError;import org.springframework.web.bind.MethodArgumentNotValidException;import org.springframework.web.bind.MissingServletRequestParameterException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseStatus;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.List;@Slf4j@RestControllerAdvice("club.mydlq.valid")public class GlobalExceptionHandler {    /**
          * 忽略參數(shù)異常處理器
          *
          * @param e 忽略參數(shù)異常
          * @return ResponseResult
          */

          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(MissingServletRequestParameterException.class)
          public ResponseResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
          log.error("", e); return new ResponseResult(ResultEnum.PARAMETER_ERROR.getCode(), "請(qǐng)求參數(shù) " + e.getParameterName() + " 不能為空");
          } /**
          * 缺少請(qǐng)求體異常處理器
          *
          * @param e 缺少請(qǐng)求體異常
          * @return ResponseResult
          */

          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(HttpMessageNotReadableException.class)
          public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
          log.error("", e); return new ResponseResult(ResultEnum.PARAMETER_ERROR.getCode(), "參數(shù)體不能為空");
          } /**
          * 參數(shù)效驗(yàn)異常處理器
          *
          * @param e 參數(shù)驗(yàn)證異常
          * @return ResponseInfo
          */

          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler(MethodArgumentNotValidException.class)
          public ResponseResult parameterExceptionHandler(MethodArgumentNotValidException e) {
          log.error("", e); // 獲取異常信息
          BindingResult exceptions = e.getBindingResult(); // 判斷異常中是否有錯(cuò)誤信息,如果存在就使用異常中的消息,否則使用默認(rèn)消息
          if (exceptions.hasErrors()) {
          List<ObjectError> errors = exceptions.getAllErrors(); if (!errors.isEmpty()) { // 這里列出了全部錯(cuò)誤參數(shù),按正常邏輯,只需要第一條錯(cuò)誤即可
          FieldError fieldError = (FieldError) errors.get(0); return new ResponseResult(ResultEnum.PARAMETER_ERROR.getCode(), fieldError.getDefaultMessage());
          }
          } return new ResponseResult(ResultEnum.PARAMETER_ERROR);
          } /**
          * 自定義參數(shù)錯(cuò)誤異常處理器
          *
          * @param e 自定義參數(shù)
          * @return ResponseInfo
          */

          @ResponseStatus(HttpStatus.BAD_REQUEST)
          @ExceptionHandler({ParamaErrorException.class})
          public ResponseResult paramExceptionHandler(ParamaErrorException e) {
          log.error("", e); // 判斷異常中是否有錯(cuò)誤信息,如果存在就使用異常中的消息,否則使用默認(rèn)消息
          if (!StringUtils.isEmpty(e.getMessage())) { return new ResponseResult(ResultEnum.PARAMETER_ERROR.getCode(), e.getMessage());
          } return new ResponseResult(ResultEnum.PARAMETER_ERROR);
          }

          }

          8、啟動(dòng)類

          9、示例測試

          下面將針對(duì)上面示例中設(shè)置的兩種接口進(jìn)行測試,分別來驗(yàn)證參數(shù)效驗(yàn)功能。

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

          使用 GET 方法請(qǐng)求地址
          http://localhost:8080/user?username=test 時(shí),返回信息:

          {
              "code"1000,
              "msg""請(qǐng)求成功"}

          當(dāng)不輸入?yún)?shù),輸入地址
          http://localhost:8080/user 時(shí),返回信息:

          {
              "code"1001,
              "msg""請(qǐng)求參數(shù) username 不能為空"}

          可以看到在執(zhí)行 GET 請(qǐng)求,能夠正常按我們?nèi)之惓L幚砥髦械脑O(shè)置處理異常信息。

          || - 測試接口 /user

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

          {
              "code"1001,
              "msg""參數(shù)體不能為空"}

          (2)、輸入部分參數(shù)進(jìn)行測試。

          請(qǐng)求內(nèi)容:

          {
           "username":"test",
           "password":"123"}

          返回信息:

          {
              "code"1001,
              "msg""userinfo不能為空"}

          (3)、輸入完整參數(shù),且設(shè)置 age > 18 時(shí),進(jìn)行測試。

          {
           "username":"111",
           "password":"sa",
            "userInfo":{
              "age":19,
              "gender":"男"  }
          }

          返回信息:

          {
              "code"1001,
              "msg""不能超過18歲"}

          可以看到在執(zhí)行 POST 請(qǐng)求,也能正常按我們?nèi)之惓L幚砥髦械脑O(shè)置處理異常信息,且提示信息為我們設(shè)置在實(shí)體類中的 Message。

          瀏覽 74
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩黄页网站大全免费在线观看 | 天天日天天舔天天爽天天操 | 久久国产精品99久久人人澡 | 91人妻人人澡 | 日韩va亚洲va欧美va清高 |