最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot使用@Validated校驗List接口參數(shù)的正確方式

 更新時間:2026年05月15日 08:55:29   作者:北風(fēng)朝向  
在 Spring Boot 開發(fā)中,接口參數(shù)校驗是保障數(shù)據(jù)完整性的第一道防線,然而,許多開發(fā)者會發(fā)現(xiàn)直接在方法參數(shù)上添加 @Validated 或 @Valid 注解往往無法生效,導(dǎo)致嵌套對象內(nèi)部的校驗規(guī)則被忽略,所以本文給大家介紹了SpringBoot使用@Validated校驗List接口參數(shù)的正確方式

引言

在 Spring Boot 開發(fā)中,接口參數(shù)校驗是保障數(shù)據(jù)完整性的第一道防線。然而,當(dāng)請求體中包含 List 或數(shù)組類型的集合參數(shù)時,許多開發(fā)者會發(fā)現(xiàn)直接在方法參數(shù)上添加 @Validated@Valid 注解往往無法生效,導(dǎo)致嵌套對象內(nèi)部的校驗規(guī)則被忽略。這并非框架的缺陷,而是由于 Bean Validation 規(guī)范(JSR-380,現(xiàn)稱為 Jakarta Validation) 默認(rèn)只校驗頂層對象,不會自動遞歸校驗集合元素。要解決這個問題,我們需要引入特定的包裝類或配置技巧。

核心痛點:為什么直接校驗 List 會失效?

Spring 的 Bean Validation 機(jī)制依賴于 Validator 接口。默認(rèn)情況下,@Valid@Validated 注解只會觸發(fā)對當(dāng)前對象的字段進(jìn)行校驗。Spring 默認(rèn)只驗證頂層對象屬性,不會自動遍歷集合元素。如果這個字段是一個 List<User>,Spring 知道要校驗 User 對象本身嗎?答案是:不知道。它只看到了一個 List 容器,而容器內(nèi)的元素并未被標(biāo)記為需要校驗的目標(biāo)。

因此,常見的錯誤寫法如下:

@PostMapping("/users")
public Result saveUsers(@RequestBody @Valid List<User> users) {
    // 這里的 @Valid 實際上沒有起到預(yù)期作用,因為 List 本身沒有約束注解
    return Result.success();
}

在這種場景下,即使 User 類中的 name 字段標(biāo)注了 @NotBlank,如果傳入空字符串,后端也不會拋出 MethodArgumentNotValidException。

解決方案一:使用自定義包裝類(推薦)

最穩(wěn)健且符合規(guī)范的做法是創(chuàng)建一個包含 List 字段的 DTO(數(shù)據(jù)傳輸對象),并在該字段上添加 @Valid 注解。這種方式結(jié)構(gòu)清晰,易于維護(hù),也是官方文檔推薦的實踐。

1. 定義實體類

首先,確保你的實體類中有明確的校驗規(guī)則:

@Data
public class User {
    @NotBlank(message = "用戶名不能為空")
    private String name;
    @Min(value = 18, message = "年齡必須大于等于18")
    private int age;
}

2. 創(chuàng)建包裝類

創(chuàng)建一個專門的包裝類來承載列表:

@Data
public class UserBatchRequest {
    // 關(guān)鍵:在此處添加 @Valid,告訴 Spring 遞歸校驗列表中的每個 User 對象
    @Valid
    @NotEmpty(message = "用戶列表不能為空")
    private List<User> users;
}

3. 控制器接收參數(shù)

在 Controller 中直接使用這個包裝類:

@RestController
@RequestMapping("/api")
public class UserController {

    @PostMapping("/batch-save")
    public Result batchSave(@RequestBody @Valid UserBatchRequest request) {
        // 此時,request.users 中的每個 User 對象都會被校驗
        userService.batchSave(request.getUsers());
        return Result.success();
    }
}

優(yōu)點

  • 語義明確:API 契約清晰,前端知道需要傳遞一個包含 users 鍵的對象。
  • 擴(kuò)展性強(qiáng):未來如果需要添加其他非列表參數(shù)(如分頁信息、操作人ID),只需在包裝類中添加字段即可。
  • 兼容性好:無需額外配置,原生支持。

全局異常處理:優(yōu)雅地返回校驗錯誤

無論采用哪種方案,校驗失敗后都需要統(tǒng)一處理異常。通過 @RestControllerAdvice 可以捕獲 MethodArgumentNotValidException,向前端返回友好的錯誤信息。

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidationExceptions(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();
        ex.getBindingResult().getFieldErrors().forEach(error -> 
            errors.put(error.getField(), error.getDefaultMessage())
        );
        // 注意:如果同一字段存在多個錯誤,上述代碼可能會覆蓋之前的錯誤。
        // 為了健壯性,建議確保 field 名稱的唯一性,或使用 List<String> 結(jié)構(gòu)存儲錯誤信息以支持同一字段的多重錯誤提示。
        return Result.fail("參數(shù)校驗失敗", errors);
    }
}

實用建議與最佳實踐

  1. 始終使用包裝類:對于任何包含集合參數(shù)的接口,優(yōu)先考慮創(chuàng)建一個 DTO 包裝類。這不僅解決了校驗問題,還提升了 API 的可讀性。官方推薦且最穩(wěn)定的方式即為這種包裝類模式,避免尋找不存在的“捷徑”。
  2. 嵌套校驗別忘了 @Valid:如果 User 類中還包含另一個對象(如 Address),且 Address 也有校驗規(guī)則,那么在 User 類的 address 字段上也必須加上 @Valid 注解,否則嵌套對象的校驗同樣會失效。
  3. 區(qū)分 @Valid@Validated
    • @Validated 是 Spring 提供的注解,主要優(yōu)勢在于支持參數(shù)級別的分組校驗(Groups);而 @Valid 是標(biāo)準(zhǔn) JSR 注解。
    • 在觸發(fā)集合內(nèi)部元素的遞歸校驗時,兩者配合 DTO 中的 @Valid 字段均可生效,但 @Validated 無法直接用于方法參數(shù)的 List 泛型元素校驗。
  4. 測試驅(qū)動:編寫單元測試時,務(wù)必構(gòu)造包含非法數(shù)據(jù)的 List,驗證全局異常處理器是否正確攔截并返回了預(yù)期的錯誤碼和信息。

總結(jié)

Spring Boot 中校驗 List 參數(shù)的關(guān)鍵在于觸發(fā)遞歸校驗。通過創(chuàng)建一個包含 @Valid 注解字段的包裝類,我們可以輕松實現(xiàn)這一目標(biāo)。這種方法簡潔、可靠且符合 Spring 的設(shè)計哲學(xué)。避免在方法簽名中直接對 List 使用 @Valid,因為它無法深入集合內(nèi)部進(jìn)行校驗。遵循這一模式,不僅能提升代碼質(zhì)量,還能減少因數(shù)據(jù)異常導(dǎo)致的線上故障。

以上就是SpringBoot使用@Validated校驗List接口參數(shù)的正確方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot @Validated校驗List接口參數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java的JSON處理器fastjson使用方法詳解

    Java的JSON處理器fastjson使用方法詳解

    下面小編就為大家?guī)硪黄狫ava的JSON處理器fastjson使用方法詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • springboot 傳參校驗@Valid及對其的異常捕獲方式

    springboot 傳參校驗@Valid及對其的異常捕獲方式

    這篇文章主要介紹了springboot 傳參校驗@Valid及對其的異常捕獲方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java 反射修改類的常量值、靜態(tài)變量值、屬性值實例詳解

    Java 反射修改類的常量值、靜態(tài)變量值、屬性值實例詳解

    在本篇文章里小編給大家整理的是一篇關(guān)于Java 反射修改類的常量值、靜態(tài)變量值、屬性值實例詳解內(nèi)容,有興趣的讀者們可以跟著學(xué)習(xí)下。
    2021-01-01
  • java面向國際化項目開發(fā)需遵循的命名規(guī)范

    java面向國際化項目開發(fā)需遵循的命名規(guī)范

    這篇文章主要為大家介紹了在參與開發(fā)國際化項目時需遵循的java命名規(guī)范,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • 關(guān)于PreparedStatement的setObject作用及說明

    關(guān)于PreparedStatement的setObject作用及說明

    這篇文章主要介紹了關(guān)于PreparedStatement的setObject作用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • APT?注解處理器實現(xiàn)?Lombok?常用注解功能詳解

    APT?注解處理器實現(xiàn)?Lombok?常用注解功能詳解

    這篇文章主要為大家介紹了使用APT?注解處理器實現(xiàn)?Lombok?常用注解功能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • Java調(diào)用Docx4j庫玩轉(zhuǎn)Word文檔處理

    Java調(diào)用Docx4j庫玩轉(zhuǎn)Word文檔處理

    在 Java 開發(fā)里處理 Word 文檔時,Docx4j 可是個超厲害的庫,它能讓咱輕松創(chuàng)建,讀取,修改和轉(zhuǎn)換 Word 文檔,下面我們就來看看具體是如何操作的吧
    2025-02-02
  • 深入了解SparkSQL的運用及方法

    深入了解SparkSQL的運用及方法

    SparkSQL就是將SQL轉(zhuǎn)換成一個任務(wù),提交到集群上運行,類似于Hive的執(zhí)行方式。本文給大家分享了SparkSQl的運用及方法,感興趣的朋友跟隨小編一起看看吧
    2022-03-03
  • Java優(yōu)化重復(fù)冗余代碼的8種方式總結(jié)

    Java優(yōu)化重復(fù)冗余代碼的8種方式總結(jié)

    日常開發(fā)中,我們經(jīng)常會遇到一些重復(fù)代碼,最近小編優(yōu)化了一些系統(tǒng)中的重復(fù)代碼,用了好幾種的方式,感覺挺有用的,所以本文給大家講講優(yōu)化重復(fù)代碼的幾種方式
    2023-08-08
  • SpringMVC異常處理的三種方式小結(jié)

    SpringMVC異常處理的三種方式小結(jié)

    本文主要介紹了SpringMVC異常處理的三種方式小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09

最新評論

滨海县| 新蔡县| 浑源县| 遵化市| 贞丰县| 濮阳市| 洛浦县| 黄石市| 小金县| 林西县| 桓台县| 阿克| 从化市| 贡山| 牡丹江市| 德江县| 句容市| 宜阳县| 平远县| 井陉县| 侯马市| 万全县| 苏州市| 尚志市| 扎赉特旗| 西盟| 清水河县| 临海市| 云和县| 沙雅县| 天等县| 郑州市| 和静县| 中牟县| 津南区| 平塘县| 二连浩特市| 宁津县| 化德县| 剑河县| 历史|