SpringBoot校驗請求Json參數


spring boot 校驗請求json參數

在后端開發中,通過接口和參數傳輸來進行與前端交互,才可以讓一個項目成型。

由於全后端隔離的方式,所以有時候需要不那么信任前端,也就是在驗證當前操作是否有權限同時,校驗前端傳來的參數的合理性也是必不可少的。

這里只記錄post json數據時候的校驗方法。


以下代碼中使用到的依賴,以及工具類,在結果的git鏈接中可以找到


  1. 一般的校驗方法

    代碼:

    // 測試接口
    @RestController
    @RequestMapping("/simple")
    public class SimpleController {
    
        // 開發中建議另外定義一個類來接受=收
        // 可以使用內部類, 不過不要寫太多
        @Data
        private static class TestParam {
            private int num;
            private String str;
        }
    
        @PostMapping("/test")
        public R<?> test(@RequestBody(required = false) TestParam param) {
    
            if (StringUtils.isNull(param)
                    || StringUtils.isEmpty(param.getStr()) || param.getNum() <= 0) {
               return R.paramErr();
            }
    
            // TODO 邏輯處理
    
            return R.ok(new JSONObject());
        }
    }
    

    測試參數:

    {
        
    }
    or
    {
        "str": 1
    }
    or
    {
        "num": 2
    }
    

    結果:

    {
        "code": "1001",
        "msg": "參數格式錯誤",
        "data": null
    }
    

    結果以及分析:

    • 表述不清楚,不管是缺少,還是不符合格式,全部返回格式錯誤(單獨判斷很冗余)。
    • 在str傳輸數字時候可以通過(給數字類型傳純字符串的處理方法在2.2第第二個處理器
  2. 接下來記錄springboot提供的參數校驗注解

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-validation</artifactId>
          <version>2.5.6</version>
      </dependency>
    
    1. 參數注解

      @Data
      private static class TestParam {
          @Min(value = 1L, message = "數字參數最小值不能小於1")
          @NotNull(message = "缺少數字參數")
          private int num;
      
          @NotNull(message = "缺少字符串參數")
          private String str;
      
          @NotNull(message = "對象參數不能為空")
          @Valid
          private TestObjParam obj;
      }
      
      @Data
      public static class TestObjParam {
          @NotNull(message = "對象參數內,參數不能為空")
          // 若還有內部對象,繼續使用 @Valid 注解即可
          private String param;
      
          @NotEmpty(message = "數組不能為空")
          private List<String> stringList;
      
          @Size(max = 2, min = 0, message = "性別參數必須在0-2之間")
          private int gender;
      }
      
      @PostMapping(value = "/test")
      Object test(@RequestBody @Validated TestParam param) {
          return "通過測試";
      }
      
    2. 與之配套使用的

      @RestControllerAdvice
      public class ControllerAdvice {
      
          /**
           * 攔截JSON參數校驗
           */
          @ResponseStatus(HttpStatus.OK)
          @ExceptionHandler(MethodArgumentNotValidException.class)
          public Map<String, String> bindException(MethodArgumentNotValidException e) {
      
              BindingResult bindingResult = e.getBindingResult();
      
              String msg = Objects.requireNonNull(
                  bindingResult.getFieldError()).getDefaultMessage();
      
              Map<String, String> result = new HashMap<>();
      
              result.put("code", "1001");
              result.put("msg", msg);
              result.put("data", null);
      
              return result;
          }
          
          /**
           * 攔截類型不匹配。也即需要字段傳對象,數字傳字符串和對象的情況
           */
          @ResponseStatus(HttpStatus.OK)
          @ExceptionHandler(HttpMessageNotReadableException.class)
          public R<?> bindException(HttpMessageNotReadableException e) {
      
              return R.paramErr("參數中有不符合目標格式的");
          }
      }
      
    3. 結果分析

      • 大大減少了在進行邏輯開發前的手動參數校驗
      • 同時前端在對接口時候也可以准確地清楚參數缺少和不符合要求的情況。
  3. 常用的參數,完整版可以在包javax.validation.constraints

    注解 解釋 所修飾類型
    @NotNull 被注解的元素不能為null 修飾所有類型參數
    @NotEmpty 不能為空 數組
    @Min(value) 被注解元素的最小值等於value 數字類型
    @Max(value) 被注解的元素的最大值等於value 數字類型
    @Size(max, min) 大小注解 數組
    @Pattern(value) 正則表達式做鑒定
  4. git地址: springboot-param-validate

  5. 補充:

    • @Range校驗數字范圍
    • @Length校驗字符串長度
    • @Size校驗String和數組長度
    • @Digits(integer = 6, fraction = 0, message = "") 修飾數字(整數位數和小數位數)
    • @BigDecimalMax和min可配合Digits
  6. 參考資料:


2022-11-17 補充分組


@Validated@Validate的簡要區別:

  1. @Validated校驗的對象中如果有對象類型的屬性, 該屬性上需要用@Validate, 可進行校驗傳遞
  2. @Validated可進行分組校驗, @Validate無分組校驗.
    分組:

import javax.validation.GroupSequence;

/**
 * 至於interface與@interface在此處的區別, 並未得知
 * 參考:
 * <a href="https://blog.csdn.net/weixin_45941064/article/details/124192836">Java @interface和interface的區別</a>
 * <a href=" https://reflectoring.io/bean-validation-with-spring-boot">Validation with Spring Boot - the Complete Guide</a>
 * <a href="https://nullbeans.com/how-to-use-java-bean-validation-in-spring-boot/">How to use Java Bean Validation in Spring Boot</a>
 * <a href="https://gitee.com/bootx/bootx-platform">bootx-platform, @cn.bootx.common.core.validation</a>
 *
 * @author wangXiaoMing
 * @date 2022/11/14 17:51
 */
public interface ValidationGroup {

    /**
     * 參數校驗分組:添加
     */
    @interface create {
    }

    /**
     * 參數校驗分組:修改
     */
    @interface update {
    }

    /**
     * 參數校驗分組:添加修改 - 也可使用序列
     */
    @interface createUpdate {
    }

    /**
     * 參數校驗分組:刪除
     */
    @interface delete {
    }

    /**
     * 參數校驗分組:查詢
     */
    @interface query {
    }

    /**
     * 先校驗update, 再校驗delete, 然后時create
     * 代表校驗順序, 和需要校驗的分組
     * <p>
     * 參考:
     * <a href="https://blog.csdn.net/qq_17586821/article/details/104661914">validation-api中@GroupSequence的使用</a>
     * <a href="https://blog.csdn.net/chepeng3577/article/details/100719210">@GroupSequence自定義驗證順序</a>
     * <a href="https://blog.csdn.net/linxingliang/article/details/122044749">validation數據校驗之分組校驗怎么玩?</a>
     */
    @GroupSequence({update.class, delete.class, create.class})
    @interface order {
    }

}

使用:
多個分組時需要使用{}, 單個時可省略
@NotNull(message = "id不能為空1", groups = {ValidationGroup.create.class})
Controller中使用時@Validated({ValidationGroup.create.class})進行校驗

分組序列@GroupSequence的使用:

  1. 指定包含的分組(其他分組不會校驗, 如上面的querycreateUpdate)
  2. 以及校驗的對應的順序


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM