SpringBoot接口參數(shù)校驗(Bean Validation)實戰(zhàn)指南
引言
在開發(fā)接口時,參數(shù)校驗是必不可少的環(huán)節(jié):前端傳參是否為空、格式是否正確、數(shù)值是否合法,都需要后端嚴格校驗,否則很容易出現(xiàn)臟數(shù)據(jù)、程序異常。
傳統(tǒng)的 if-else 判空不僅代碼臃腫,還容易遺漏,維護成本極高。
SpringBoot 官方推薦使用 Bean Validation(JSR-380) 實現(xiàn)優(yōu)雅的參數(shù)校驗,通過注解一鍵完成校驗,配合全局異常處理,讓接口更健壯、代碼更簡潔。
今天就來介紹一下基礎(chǔ)注解、實戰(zhàn)使用、分組校驗、自定義注解、嵌套校驗、全局異常處理。
一、為什么要用 Bean Validation?
告別繁瑣 if-else:不用寫大量判空、判斷邏輯,代碼更簡潔
注解式開發(fā):一個注解完成一類校驗,可讀性極強
校驗規(guī)則統(tǒng)一:團隊協(xié)作無歧義
配合全局異常:校驗失敗自動返回友好提示,無需手動處理
支持復雜場景:分組校驗、自定義校驗、嵌套對象校驗
二、核心依賴引入
SpringBoot 2.x 版本直接引入以下依賴即可:
<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-validationartifactId> <dependency> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> <dependency>
三、最常用校驗注解
1. 空與非空校驗
@NotBlank:字符串不能為 null,且去除空格后長度大于0(專用字符串)
@NotNull:不能為 null,但可以是空字符串、空集合
@NotEmpty:不能為 null,且長度/大小大于0(字符串、集合、數(shù)組)
2. 數(shù)值校驗
@Min:數(shù)值最小值@Max:數(shù)值最大值@Positive:正數(shù)@PositiveOrZero:正數(shù)或0@Negative:負數(shù)@NegativeOrZero:負數(shù)或0
3. 格式校驗
@Email:郵箱格式@Pattern:正則表達式自定義格式@Length:字符串長度限制
4. 日期與時間
@Past:必須是過去時間@PastOrPresent:過去或當前時間@Future:必須是未來時間@FutureOrPresent:未來或當前時間
四、單對象參數(shù)校驗
1. 封裝實體類 + 校驗注解
importlombok.Data;
importjavax.validation.constraints.*;
/**
* 用戶參數(shù)接收類
*/
@Data
publicclassUserDTO{
@NotBlank(message ="用戶ID不能為空")
privateString userId;
@NotBlank(message ="用戶名不能為空")
@Length(min =2, max =10, message ="用戶名長度必須在2-10位之間")
privateString username;
@NotNull(message ="年齡不能為空")
@Min(value =18, message ="年齡必須大于等于18歲")
@Max(value =60, message ="年齡必須小于等于60歲")
privateInteger age;
@Email(message ="郵箱格式不正確")
@NotBlank(message ="郵箱不能為空")
privateString email;
@Pattern(regexp ="^1[3-9]\\d{9}$", message ="手機號格式不正確")
privateString phone;
}2. Controller 開啟校驗(@Valid)
@Valid 是開啟校驗的核心注解,必須添加在參數(shù)前:
importorg.springframework.validation.BindingResult;
importorg.springframework.web.bind.annotation.PostMapping;
importorg.springframework.web.bind.annotation.RequestBody;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
importjavax.validation.Valid;
@RestController
@RequestMapping("/user")
publicclassUserController{
/**
* 新增用戶
*/
@PostMapping("/add")
publicResult<String>addUser(@Valid@RequestBodyUserDTO userDTO){
// 校驗通過,執(zhí)行業(yè)務(wù)邏輯
returnResult.success("用戶新增成功");
}
}五、配合全局異常處理
參數(shù)校驗失敗會拋出 MethodArgumentNotValidException,我們在全局異常處理器中捕獲,統(tǒng)一返回格式:
importlombok.extern.slf4j.Slf4j;
importorg.springframework.web.bind.MethodArgumentNotValidException;
importorg.springframework.web.bind.annotation.ExceptionHandler;
importorg.springframework.web.bind.annotation.RestControllerAdvice;
importjava.util.stream.Collectors;
@Slf4j
@RestControllerAdvice
publicclassGlobalExceptionHandler{
/**
* 捕獲參數(shù)校驗異常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
publicResult<String>handleValidException(MethodArgumentNotValidException e){
// 拼接所有錯誤提示
String errorMsg = e.getBindingResult().getFieldErrors().stream()
map(error -> error.getField()+":"+ error.getDefaultMessage())
collect(Collectors.joining(";"));
log.error("參數(shù)校驗異常:{}", errorMsg);
returnResult.fail(400, errorMsg);
}
}校驗失敗返回示例
{
"code":400,
"msg":"年齡必須大于等于18歲;郵箱格式不正確",
"data":null
}六、分組校驗
實際業(yè)務(wù)中,新增和修改的校驗規(guī)則不同:
- 新增:不需要傳 ID
- 修改:必須傳 ID
使用分組校驗可完美解決。
1. 定義分組接口
/**
* 新增分組
*/
publicinterfaceAddGroup{
}
/**
* 修改分組
*/
publicinterfaceUpdateGroup{
}2. 實體類標注分組
@Data
publicclassUserDTO{
// 修改時必須傳ID,新增時不需要
@NotBlank(message ="用戶ID不能為空", groups =UpdateGroup.class)
privateString userId;
@NotBlank(message ="用戶名不能為空", groups ={AddGroup.class,UpdateGroup.class})
privateString username;
}3. Controller 指定分組
使用 @Validated 注解指定分組:
@RestController
@RequestMapping("/user")
@Validated
publicclassUserController{
// 新增:使用 AddGroup 分組校驗
@PostMapping("/add")
publicResult<String>add(@Validated(AddGroup.class)@RequestBodyUserDTO userDTO){
returnResult.success("新增成功");
}
// 修改:使用 UpdateGroup 分組校驗
@PostMapping("/update")
publicResult<String>update(@Validated(UpdateGroup.class)@RequestBodyUserDTO userDTO){
returnResult.success("修改成功");
}
}七、自定義校驗注解
當內(nèi)置注解不滿足業(yè)務(wù)時,可自定義注解,例如校驗性別只能是男/女。
1. 自定義注解@Gender
importjavax.validation.Constraint;
importjavax.validation.Payload;
importjava.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy =GenderValidator.class)// 綁定校驗器
public@interfaceGender{
Stringmessage()default"性別只能輸入:男/女";
Class<?>[]groups()default{};
Class<?extendsPayload>[]payload()default{};
}2. 自定義校驗器
importjavax.validation.ConstraintValidator;
importjavax.validation.ConstraintValidatorContext;
publicclassGenderValidatorimplementsConstraintValidator<Gender,String>{
@Override
publicbooleanisValid(String value,ConstraintValidatorContext context){
// 校驗邏輯
return"男".equals(value)||"女".equals(value);
}
}3. 使用自定義注解
@Gender privateString gender;
八、嵌套對象校驗
如果參數(shù)是嵌套對象,需要在嵌套對象上添加 @Valid 才能開啟校驗:
@Data
publicclassUserDTO{
@NotBlank
privateString username;
@Valid// 開啟嵌套校驗
@NotNull(message ="地址信息不能為空")
privateAddressDTO address;
}
@Data
classAddressDTO{
@NotBlank(message ="詳細地址不能為空")
privateString detail;
@NotBlank(message ="城市不能為空")
privateString city;
}九、單個參數(shù)校驗(非實體類)
如果接口是零散參數(shù),在類上添加 @Validated,直接給參數(shù)加注解:
@RestController
@RequestMapping("/user")
@Validated
publicclassUserController{
@GetMapping("/get")
publicResult<String>getUser(
@NotBlank(message ="用戶ID不能為空")String userId,
@NotNull(message ="狀態(tài)不能為空")Integer status
){
returnResult.success("查詢成功");
}
}十、總結(jié)
@Valid:開啟實體類參數(shù)校驗@Validated:開啟分組校驗、單個參數(shù)校驗- 常用注解:
@NotBlank、@NotNull、@Min、@Max、@Email - 全局異常捕獲:校驗失敗自動返回友好提示
- 分組校驗:適配新增/修改不同規(guī)則
- 自定義注解:滿足復雜業(yè)務(wù)校驗
學會這套參數(shù)校驗方案,你的接口健壯性、規(guī)范性、安全性直接拉滿!
以上就是SpringBoot接口參數(shù)校驗(Bean Validation)實戰(zhàn)指南的詳細內(nèi)容,更多關(guān)于SpringBoot接口參數(shù)校驗的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用SpringBoot集成Thymeleaf和Flying?Saucer實現(xiàn)PDF導出
在?Spring?Boot?項目中,生成?PDF?報表或發(fā)票是常見需求,本文將介紹如何使用?Spring?Boot?集成?Thymeleaf?模板引擎和?Flying?Saucer?實現(xiàn)?PDF?導出,并提供詳細的代碼實現(xiàn)和常見問題解決方案,需要的朋友可以參考下2024-11-11
mybatis查詢到了數(shù)據(jù),但是實體類個別字段為null問題
這篇文章主要介紹了mybatis查詢到了數(shù)據(jù),但是實體類個別字段為null問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
淺談java中math類中三種取整函數(shù)的區(qū)別
下面小編就為大家?guī)硪黄獪\談java中math類中三種取整函數(shù)的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11
Java 數(shù)據(jù)結(jié)構(gòu)之時間復雜度與空間復雜度詳解
算法復雜度分為時間復雜度和空間復雜度。其作用: 時間復雜度是度量算法執(zhí)行的時間長短;而空間復雜度是度量算法所需存儲空間的大小2021-11-11
springcloud本地服務(wù)不注冊到注冊中心的解決方案
這篇文章主要介紹了springcloud本地服務(wù)不注冊到注冊中心,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07

