深入解析@Validated注解:Spring 驗證機制的核心工具


一、注解出處與核心定位

1. 注解來源

? 所屬框架@ValidatedSpring Framework 提供的注解(org.springframework.validation.annotation 包下)。
? 核心定位
作為 Spring 對 JSR-380(Bean Validation 2.0+) 規范的增強實現,用于觸發方法參數、返回值或類成員變量的校驗邏輯。
與標準Valid`(JSR 原生注解)相比,支持 分組驗證層級校驗,更貼合 Spring 生態。


二、基礎使用步驟

1. 添加依賴(Spring Boot 示例)

pom.xml 中引入 Bean Validation 實現:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. 啟用校驗支持

在 Spring Boot 中無需額外配置,自動生效

3. 編寫校驗規則(DTO/VO)

在數據對象中標注 Bean Validation 注解java

public class UserCreateDTO {
@NotNull(message = "ID 不能為空")
private Long id;@NotEmpty(message = "用戶名不能為空")
private String username;@NotBlank(message = "密碼不能為空或純空格")
private String password;@Size(min = 6, max = 20, message = "密碼長度需在6-20位之間")
private String password;@Email(message = "郵箱格式不正確")
private String email;@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手機號格式錯誤")
private String phone;@Min(value = 18, message = "年齡需≥18歲")
private Integer age;@DecimalMin(value = "0.0", inclusive = false, message = "價格必須大于0")
private BigDecimal price;@Positive(message = "庫存必須為正數")
private Integer stock;@NegativeOrZero(message = "折扣率需≤0")
private BigDecimal discountRate;@Past(message = "出生日期必須早于當前時間")
private LocalDate birthday;@Future(message = "預約時間必須晚于當前時間")
private LocalDateTime appointmentTime;@Length(min = 2, max = 10, message = "名稱長度需在2-10字符之間")
private String name;@Range(min = 1, max = 100, message = "數量需在1-100之間")
private Integer quantity;@URL(protocol = "https", message = "僅支持HTTPS鏈接")
private String website;@CreditCardNumber(message = "信用卡號無效")
private String cardNumber;@SafeHtml(message = "包含非法HTML標簽")
private String description;
}

4. 觸發校驗(Controller 層)

在 Controller 方法參數前使用 @Validated@Valid

@RestController
public class UserController {@PostMapping("/users")public ResponseEntity<?> createUser(@RequestBody @Validated UserCreateDTO dto) { // 觸發校驗// 業務邏輯return ResponseEntity.ok().build();}
}

5. 處理校驗異常

通過 @ExceptionHandler 捕獲校驗失敗異常,返回統一錯誤響應:

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {List<String> errors = ex.getBindingResult().getFieldErrors().stream().map(error -> error.getField() + ": " + error.getDefaultMessage()).toList();return ResponseEntity.badRequest().body(new ErrorResponse("參數校驗失敗", errors));}
}

三、進階功能與使用拓展

1. 分組校驗(多場景復用規則)

場景說明
  • 創建用戶時:所有字段必填
  • 更新用戶時:允許不修改密碼(密碼字段非必填)
步驟實現

1. 定義分組接口

public interface CreateGroup {}  // 創建分組標記
public interface UpdateGroup {}  // 更新分組標記

2. 在 DTO 中指定分組

public class UserDTO {@NotBlank(groups = {CreateGroup.class, UpdateGroup.class})private String username;@NotBlank(groups = CreateGroup.class)  // 僅創建時校驗private String password;
}

3. Controller 方法指定生效分組

@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody @Validated(CreateGroup.class) UserDTO dto) { // 僅校驗 CreateGroup 分組規則
}@PutMapping("/users/{id}")
public ResponseEntity<?> updateUser(@PathVariable Long id,@RequestBody @Validated(UpdateGroup.class) UserDTO dto) { // 僅校驗 UpdateGroup 分組規則
}

2. 方法級別校驗(Service 層驗證)

在 Service 接口/實現類中使用 @Validated 觸發方法參數校驗:

@Service
@Validated  //級別開啟校驗
public class UserService {public void updateEmail(@NotNull Long userId, @Email String newEmail) {  // 直接標注校驗規則// 業務邏輯}
}

3. 自定義校驗注解

需求示例

驗證手機號格式(自定義規則)。

實現步驟

1. 定義注解 @Phone

@Documented
@Constraint(validatedBy = PhoneValidator.class)
@Target({FIELD, PARAMETER})
@Retention(RUNTIME)
public @interface Phone {String message() default "手機號格式不正確";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}

2. 編寫校驗器 PhoneValidator

public class PhoneValidator implements ConstraintValidator<Phone, String> {private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\\d{9}$");@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {if (value == null) return true;  // 結合 @NotNull 使用return PHONE_PATTERN.matcher(value).matches();}
}

3. 在 DTO 中使用

public class UserDTO {@Phoneprivate String phone;
}

4. 級聯校驗(嵌套對象驗證)

當對象包含其他對象成員時,使用 @Valid 觸發嵌套校驗:

public class OrderCreateDTO {@Valid  // 觸發 AddressDTO 內部校驗@NotNull(message = "收貨地址不能為空")private AddressDTO address;// 其他字段...
}public class AddressDTO {@NotBlankprivate String city;@NotBlankprivate String street;
}

四、原理與關鍵機制

1. 校驗觸發流程

  1. 代理攔截:Spring 通過 AOP 代理攔截帶有 @Validated 注解的類方法。
  2. 參數解析:在方法執行前,校驗參數是否符合約束。
  3. 異常拋出:若校驗失敗,拋出 ConstraintViolationException(方法級別)或 MethodArgumentNotValidException(Controller 層)。
  4. 異常處理:通過 HandlerExceptionResolver@ExceptionHandler 處理錯誤。

2. 與 @Valid 的核心差異

特性@Valid (JSR-380)@Validated (Spring)
分組支持不支持支持
校驗范圍僅方法參數、字段方法參數、返回值、類成員變量
層級校驗觸發需顯式添加 @Valid可自動級聯
適用場景簡單 Bean 校驗Spring 生態復雜校驗需求

五、常見問題與排查

1. 校驗注解不生效

? 可能原因
? 未添加 spring-boot-starter-validation 依賴
? 未在類上標注 @Validated(方法級別校驗)
? 校驗方法未被 Spring 代理(如內部方法調用)

2. 分組校驗未按預期執行

? 檢查點
? Controller/Service 方法是否指定了正確的 groups
? 分組接口是否正確定義(空接口即可,無需實現)

3. 自定義校驗器未生效

? 排查步驟
? 確保 ConstraintValidator 實現類被 Spring 管理(如添加 @Component
? 檢查注解的 @Constraint(validatedBy) 指向正確類


六、最佳實踐總結

  1. 分層校驗
    ? Controller 層:處理基礎數據格式校驗
    ? Service 層:執行業務規則校驗(如庫存檢查)

  2. 合理分組:避免為不同場景創建重復 DTO,通過分組復用校驗規則。

  3. 統一異常處理:全局捕獲校驗異常,返回結構化的錯誤信息。

  4. 性能優化
    ? 避免在復雜校驗中執行數據庫操作(優先通過緩存或異步校驗)
    ? 對高頻接口禁用實時校驗(如通過 groups 動態控制)

通過靈活運用 @Validated,開發者可以構建健壯維護的校驗體系,顯著提升代碼質量和系統可靠性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/75699.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/75699.shtml
英文地址,請注明出處:http://en.pswp.cn/web/75699.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025年認證杯數學建模競賽A題完整分析論文(含模型、可運行代碼)(共32頁)

2025年認證杯數學建模競賽A題完整分析論文 目錄 摘要 一、問題分析 二、問題重述 三、模型假設 四、 模型建立與求解 4.1問題1 4.1.1問題1解析 4.1.2問題1模型建立 4.1.3問題1樣例代碼&#xff08;僅供參考&#xff09; 4.1.4問題1求解結果分析&#xff08…

Google A2A協議,是為了戰略性占領標準?

一、導讀 2025 年 4 月 9 日&#xff0c;Google 正式發布了 Agent2Agent&#xff08;A2A&#xff09;協議。 A2A 協議致力于打破智能體之間的隔閡&#xff0c;讓它們能夠跨越框架和供應商的限制&#xff0c;以一種標準化、開放的方式進行溝通與協作 截止到現在&#xff0c;代…

Ansible:roles角色

文章目錄 Roles角色Ansible Roles目錄編排Roles各目錄作用創建 roleplaybook調用角色調用角色方法1&#xff1a;調用角色方法2&#xff1a;調用角色方法3&#xff1a; roles 中 tags 使用實戰案例 Roles角色 角色是ansible自1.2版本引入的新特性&#xff0c;用于層次性、結構化…

MCU的USB接口作為 USB CDC串口輸出

引用&#xff1a; https://microchip-mplab-harmony.github.io/usb_apps_device/apps/usb_uart_bridge_dual/readme.html STM32 USB使用記錄&#xff1a;使用CDC類虛擬串口&#xff08;VCP&#xff09;進行通訊_stm32 usb使用記錄:使用cdc類虛擬串口(vcp)進行通訊-CSDN博客 前…

深度解析強化學習:原理、算法與實戰

深度解析強化學習:原理、算法與實戰 0. 前言1. 強化學習基礎1.1 基本概念1.2 馬爾科夫決策過程1.3 目標函數1.4 智能體學習過程2. 計算狀態值3. 計算狀態-動作值4. Q 學習4.1 Q 值4.2 使用 Q 學習進行 frozen lake 游戲4.3. frozen lake 問題4.4 實現 Q 學習小結系列鏈接0. 前…

UE5藍圖之間的通信------接口

一、創建藍圖接口 二、雙擊創建的藍圖接口&#xff0c;添加函數&#xff0c;并重命名新函數。 三、在一個藍圖&#xff08;如玩家角色藍圖&#xff09;中實現接口&#xff0c;如下圖&#xff1a; 步驟一&#xff1a;點擊類設置 步驟二&#xff1a;在細節面板已經實現的接口中…

2025 年“認證杯”數學中國數學建模網絡挑戰賽 A題 小行星軌跡預測

近地小行星&#xff08; Near Earth Asteroids, NEAs &#xff09;是軌道相對接近地球的小行 星&#xff0c;它的正式定義為橢圓軌道的近日距不大于 1.3 天文單位&#xff08; AU &#xff09;的小行星。 其中軌道與地球軌道最近距離小于 0.05A 且直徑大于 140 米的小行星被…

Axure中繼器(Repeater): 列表多選和 列表查詢

文章目錄 引言I 列表多選添加選中交互事件添加未選中交互事件II 列表查詢知識點操作說明引言 基于鼠標點擊交互事件實現列表多選列表查詢 I 列表多選 添加選中交互事件 給列標題第一列多選框元件命名為ckeck,并同時添加選中交互事件; 同步添加設置選擇/選中動作,目標元件選…

windows11下pytorch(cpu)安裝

先裝anaconda 見最下方 Pytorch 官網&#xff1a;PyTorch 找到下圖&#xff08;不要求版本一樣&#xff09;&#xff08;我的電腦是集顯&#xff08;有navdia的裝gpu&#xff09;&#xff0c;裝cpu&#xff09; 查看已有環境列表 創建環境 conda create –n 虛擬環境名字(…

最新版IDEA超詳細圖文安裝教程(適用Mac系統)附安裝包及補丁2025最新教程

目錄 前言 一、IDEA最新版下載 二、IDEA安裝 三、IDEA補丁 前言 IDEA&#xff08;IntelliJ IDEA&#xff09;是專為Java語言設計的集成開發環境&#xff08;IDE&#xff09;&#xff0c;由JetBrains公司開發&#xff0c;被公認為業界最優秀的Java開發工具之一。DEA全稱Int…

react從零開始的基礎課1

全文約5萬字。 1.hello,.. // App.jsx import { useState } from react import reactLogo from ./assets/react.svg import viteLogo from /vite.svg import ./App.cssfunction App() {const [count, setCount] useState(0)return (<><Greeting name"world&qu…

【linux知識】web服務環境搭建(一):用戶以及開發環境初始化

toc 創建用戶組以及用戶 以下是 創建用戶組 wendao 和用戶 wendao 并指定 GID、UID 及家目錄 的完整操作指南&#xff1a; 一、創建用戶組&#xff08;指定 GID&#xff09; sudo groupadd -g 1500 wendao # 創建組并指定 GID 為 1500? 注意&#xff1a;GID 需唯一&#…

音視頻 五 看書的筆記 MediaCodec

MediaCodec 用于訪問底層媒體編解碼器框架&#xff0c;編解碼組件。通常與MediaExtractor(解封裝,例如Mp4文件分解成 video和audio)、MediaSync、MediaMuxer(封裝 例如音視頻合成Mp4文件)、MediaCrypto、Image(cameraX 回調的ImageReader對象可以獲取到Image幀圖像,可轉換成YU…

李宏毅NLP-3-語音識別part2-LAS

語音識別part2——LAS Listen Listen主要功能是提取內容信息&#xff0c;去除說話人差異和噪聲 。編碼器&#xff08;Encoder&#xff09;結構&#xff0c;輸入是聲學特征&#xff0c;經過 Encoder 處理后&#xff0c;輸出為高級表示&#xff0c;這些高級表示可用于后續語音識別…

開源CMS的模塊化設計和API接口如何具體影響其擴展性?

優秀的CMS系統都有自己主打的特點&#xff0c;開源CMS憑借其靈活性和低成本優勢占據了市場主流地位&#xff0c;而模塊化設計與API接口正是其擴展性的兩大基石。本文將深入探討這兩大技術特性是如何影響cms的擴展性的。 一、模塊化設計&#xff1a;功能解耦與生態繁榮的引擎 …

一文讀懂WPF系列之常用控件以及樣式

WPF控件 控件分類概覽常用控件常用控件代碼示例和效果 樣式與模板應用樣式定義??方式行內樣式??頁面/窗口級資源樣式&#xff08;Local Resource&#xff09;應用程序全局資源獨立資源字典&#xff08;ResourceDictionary&#xff09;控件模板&#xff08;ControlTemplate&…

AndroidTV D貝桌面-v3.2.5-[支持文件傳輸]

AndroidTV D貝桌面 鏈接&#xff1a;https://pan.xunlei.com/s/VONXSBtgn8S_BsZxzjH_mHlAA1?pwdzet2# AndroidTV D貝桌面-v3.2.5[支持文件傳輸] 第一次使用的話&#xff0c;壁紙默認去掉的&#xff0c;不需要按遙控器上鍵&#xff0c;自己更換壁紙即可

XDocument和XmlDocument的區別及用法

因為這幾天用到了不熟悉的xml統計數據&#xff0c;啃了網上的資料解決了問題&#xff0c;故總結下xml知識。 1.什么是XML?2.XDocument和XmlDocument的區別3.XDocument示例1示例2&#xff1a;示例3&#xff1a; 4.XmlDocument5.LINQ to XML6.XML序列化(Serialize)與反序列化(De…

從競速到巡檢:不同無人機如何匹配最佳PCB方案?

隨著無人機技術的快速發展&#xff0c;高性能PCB&#xff08;印刷電路板&#xff09;成為無人機制造商的核心需求之一。無論是消費級無人機還是工業級應用&#xff0c;PCB的質量直接影響飛行控制、信號傳輸和整機穩定性。那么&#xff0c;無人機制造商在選型高端PCB時&#xff…

高支模自動化監測解決方案

1.行業現狀 高大模板支撐系統在澆筑施工過程中&#xff0c;諸多重大安全風險點進行實時自動化安全監測的解決方案主要監測由于頂桿失穩、扣件失效、承壓過大等引起的支撐軸力、模板沉降、相對位移、支撐體系傾斜等參數變化。系統采用無線自動組網、高頻連續采樣&#xff0c;實時…