spring boot 校驗請求json參數
在后端開發中,通過接口和參數傳輸來進行與前端交互,才可以讓一個項目成型。
由於全后端隔離的方式,所以有時候需要不那么信任前端,也就是在驗證當前操作是否有權限同時,校驗前端傳來的參數的合理性也是必不可少的。
這里只記錄post json數據時候的校驗方法。
以下代碼中使用到的依賴,以及工具類,在結果的git鏈接中可以找到
-
一般的校驗方法
代碼:
// 測試接口 @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第第二個處理器)
-
接下來記錄springboot提供的參數校驗注解
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> <version>2.5.6</version> </dependency>-
參數注解
@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 "通過測試"; } -
與之配套使用的
@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("參數中有不符合目標格式的"); } } -
結果分析
- 大大減少了在進行邏輯開發前的手動參數校驗
- 同時前端在對接口時候也可以准確地清楚參數缺少和不符合要求的情況。
-
-
常用的參數,完整版可以在包
javax.validation.constraints中注解 解釋 所修飾類型 @NotNull 被注解的元素不能為null 修飾所有類型參數 @NotEmpty 不能為空 數組 @Min(value) 被注解元素的最小值等於value 數字類型 @Max(value) 被注解的元素的最大值等於value 數字類型 @Size(max, min) 大小注解 數組 @Pattern(value) 正則表達式做鑒定 -
git地址: springboot-param-validate
-
補充:
- @Range校驗數字范圍
- @Length校驗字符串長度
- @Size校驗String和數組長度
- @Digits(integer = 6, fraction = 0, message = "") 修飾數字(整數位數和小數位數)
- @BigDecimalMax和min可配合Digits
-
參考資料:
- 如何使用springboot優雅地校驗請求參數
- Spring方法級別數據校驗:@Validated + MethodValidationPostProcessor優雅的完成數據校驗動作
- @Validated注解詳解,分組校驗,嵌套校驗,@Valid和@Validated 區別,Spring Boot @Validated
- @Validated和@Valid的區別?校驗級聯屬性(內部類)
- 【參數校驗框架】@Validated 嵌套校驗的使用
- validation校驗規則
- springboot項目中自定義注解的使用總結、java自定義注解實戰(常用注解DEMO)
- Spring和SpringBoot常用注解
2022-11-17 補充分組
@Validated與@Validate的簡要區別:
@Validated校驗的對象中如果有對象類型的屬性, 該屬性上需要用@Validate, 可進行校驗傳遞@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的使用:
- 指定包含的分組(其他分組不會校驗, 如上面的
query和createUpdate) - 以及校驗的對應的順序
