Spring Validation中9個數據校驗工具

Spring Validation作為Spring生態系統的重要組成部分,提供了一套強大而靈活的數據校驗機制。

1. Bean Validation基礎注解

Spring Validation集成了JSR-380 (Bean Validation 2.0)規范,提供了一系列開箱即用的校驗注解。

常用注解示例

@Data
public class UserDTO {@NotNull(message = "用戶ID不能為空")private Long id;@NotBlank(message = "用戶名不能為空")@Size(min = 4, max = 20, message = "用戶名長度必須在4到20個字符之間")private String username;@Email(message = "郵箱格式不正確")private String email;@Min(value = 18, message = "年齡必須大于或等于18")@Max(value = 120, message = "年齡必須小于或等于120")private Integer age;@Past(message = "出生日期必須是過去的日期")private LocalDate birthDate;@Pattern(regexp = "^1[3-9]\d{9}$", message = "手機號碼格式不正確")private String phoneNumber;
}

在控制器中應用

@RestController
@RequestMapping("/api/users")
public class UserController {@PostMappingpublic ResponseEntity<UserDTO> createUser(@RequestBody @Valid UserDTO userDTO, BindingResult bindingResult) {if (bindingResult.hasErrors()) {// 處理驗證錯誤throw new ValidationException(bindingResult);}// 處理業務邏輯return ResponseEntity.ok(userDTO);}
}

最佳實踐:使用有意義的錯誤消息,保持一致的命名風格,避免在實體類上直接使用驗證注解,而是在DTO對象上應用驗證規則。

2. 自定義約束驗證器

Spring Validation允許開發者創建自定義約束,滿足特定業務規則的驗證需求。

定義自定義約束注解

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueUsernameValidator.class)
public @interface UniqueUsername {String message() default "用戶名已存在";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}

實現驗證器

public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {@Autowiredprivate UserRepository userRepository;@Overridepublic boolean isValid(String username, ConstraintValidatorContext context) {if (username == null) {return true;  // 讓@NotNull處理空值}return !userRepository.existsByUsername(username);}
}

應用自定義約束

public class UserRegistrationDTO {@NotBlank@Size(min = 4, max = 20)@UniqueUsernameprivate String username;// 其他字段...
}

使用場景:驗證業務特定規則,如唯一性約束、密碼復雜度、信用卡格式等。

3. 分組驗證

分組驗證允許根據不同場景應用不同的驗證規則,例如創建和更新操作可能需要不同的驗證邏輯。

定義驗證分組

// 定義驗證分組接口
public interface ValidationGroups {interface Create {}interface Update {}
}

應用分組到約束

@Data
public class ProductDTO {@Null(groups = ValidationGroups.Create.class, message = "創建產品時ID必須為空")@NotNull(groups = ValidationGroups.Update.class, message = "更新產品時ID不能為空")private Long id;@NotBlank(groups = {ValidationGroups.Create.class, ValidationGroups.Update.class})private String name;@PositiveOrZero(groups = ValidationGroups.Create.class)@Positive(groups = ValidationGroups.Update.class)private BigDecimal price;
}

在控制器中指定分組

@RestController
@RequestMapping("/api/products")
public class ProductController {@PostMappingpublic ResponseEntity<ProductDTO> createProduct(@RequestBody @Validated(ValidationGroups.Create.class) ProductDTO productDTO) {// 創建產品邏輯return ResponseEntity.ok(productDTO);}@PutMapping("/{id}")public ResponseEntity<ProductDTO> updateProduct(@PathVariable Long id,@RequestBody @Validated(ValidationGroups.Update.class) ProductDTO productDTO) {// 更新產品邏輯return ResponseEntity.ok(productDTO);}
}

提示:注意使用@Validated注解而不是@Valid,因為只有前者支持分組驗證。

4. 嵌套驗證

嵌套驗證允許驗證復雜對象結構中的嵌套對象。

定義嵌套對象

@Data
public class OrderDTO {@NotNullprivate Long id;@NotNull@Valid  // 標記需要級聯驗證的字段private CustomerDTO customer;@NotEmpty@Valid  // 驗證集合中的每個元素private List<OrderItemDTO> items;
}@Data
public class CustomerDTO {@NotNullprivate Long id;@NotBlankprivate String name;@Emailprivate String email;@Valid  // 進一步嵌套驗證private AddressDTO address;
}

關鍵點:在需要級聯驗證的字段上添加@Valid注解,確保驗證深入到嵌套對象中。

5. 方法級別驗證

Spring Validation不僅可以用于控制器參數,還可以應用于服務層的方法。

啟用方法級別驗證

@Configuration
@EnableMethodValidation
public class ValidationConfig {// 配置內容
}

定義帶驗證的服務方法

@Service
public class UserService {@Validatedpublic User createUser(@Valid UserDTO userDTO) {// 業務邏輯return new User();}@NotNullpublic User findById(@Min(1) Long id) {// 查詢邏輯return new User();}@Validated(ValidationGroups.Update.class)public void updateUser(@Valid UserDTO userDTO) {// 更新邏輯}
}

應用場景:確保服務層方法接收到的參數和返回的結果符合預期,增強代碼的健壯性。

6. 錯誤消息處理和國際化

Spring Validation提供了強大的錯誤消息處理和國際化支持。

自定義錯誤消息

ValidationMessages.properties文件中定義:

# ValidationMessages.properties
javax.validation.constraints.NotEmpty.message=字段不能為空
javax.validation.constraints.Email.message=不是有效的電子郵箱地址
user.name.size=用戶名長度必須在{min}到{max}個字符之間

國際化錯誤消息

創建特定語言的屬性文件:

# ValidationMessages_en.properties
javax.validation.constraints.NotEmpty.message=Field cannot be empty
javax.validation.constraints.Email.message=Not a valid email address
user.name.size=Username must be between {min} and {max} characters# ValidationMessages_zh_CN.properties
javax.validation.constraints.NotEmpty.message=字段不能為空
javax.validation.constraints.Email.message=不是有效的電子郵箱地址
user.name.size=用戶名長度必須在{min}到{max}個字符之間

使用自定義消息

@Size(min = 4, max = 20, message = "{user.name.size}")
private String username;

7. 程序化驗證

除了注解驅動的驗證,Spring Validation還支持以編程方式進行驗證。

使用Validator手動驗證對象

@Service
public class ValidationService {private final Validator validator;public ValidationService(Validator validator) {this.validator = validator;}public <T> void validate(T object) {Set<ConstraintViolation<T>> violations = validator.validate(object);if (!violations.isEmpty()) {throw new ConstraintViolationException(violations);}}public <T> void validateWithGroup(T object, Class<?>... groups) {Set<ConstraintViolation<T>> violations = validator.validate(object, groups);if (!violations.isEmpty()) {throw new ConstraintViolationException(violations);}}public <T> List<String> getValidationErrors(T object) {return validator.validate(object).stream().map(ConstraintViolation::getMessage).collect(Collectors.toList());}
}

使用場景:在復雜業務邏輯中需要條件性驗證,或者驗證非控制器傳入的對象時。

8. 組合約束

組合約束允許將多個基本約束組合成一個更復雜的約束,減少代碼重復。

創建組合約束

@NotNull
@Size(min = 8, max = 30)
@Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$", message = "密碼必須包含至少一個數字、小寫字母、大寫字母和特殊字符")
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
public @interface StrongPassword {String message() default "密碼不符合安全要求";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}

應用組合約束

public class PasswordChangeDTO {@NotBlankprivate String oldPassword;@StrongPasswordprivate String newPassword;@NotBlankprivate String confirmPassword;
}

優點:提高代碼可讀性和可維護性,確保驗證規則在整個應用中保持一致。

9. 跨字段驗證

跨字段驗證允許根據多個字段之間的關系進行驗證。

創建類級別約束

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordMatchesValidator.class)
public @interface PasswordMatches {String message() default "確認密碼與新密碼不匹配";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};String field();String fieldMatch();
}

實現驗證器

public class PasswordMatchesValidator implements ConstraintValidator<PasswordMatches, Object> {private String field;private String fieldMatch;@Overridepublic void initialize(PasswordMatches constraintAnnotation) {this.field = constraintAnnotation.field();this.fieldMatch = constraintAnnotation.fieldMatch();}@Overridepublic boolean isValid(Object value, ConstraintValidatorContext context) {try {Object fieldValue = BeanUtils.getPropertyDescriptor(value.getClass(), field).getReadMethod().invoke(value);Object fieldMatchValue = BeanUtils.getPropertyDescriptor(value.getClass(), fieldMatch).getReadMethod().invoke(value);return (fieldValue != null) && fieldValue.equals(fieldMatchValue);} catch (Exception e) {return false;}}
}

應用類級別約束

@Data
@PasswordMatches(field = "newPassword", fieldMatch = "confirmPassword")
public class PasswordChangeDTO {@NotBlankprivate String oldPassword;@StrongPasswordprivate String newPassword;@NotBlankprivate String confirmPassword;
}

使用場景:驗證密碼確認、日期范圍比較、最小/最大值比較等。

總結

Spring Validation提供了一套全面而強大的數據校驗工具,從基本的注解驗證到復雜的自定義約束,從單一字段驗證到跨字段關系驗證,都有相應的解決方案。

合理利用這些驗證工具,不僅能提高應用的健壯性和安全性,還能改善代碼質量和可維護性。

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

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

相關文章

AI 搜索引擎 MindSearch

背景 RAG是一種利用文檔減少大模型的幻覺&#xff0c;AI搜索也是 AI 搜索引擎 MindSearch 是一個開源的 AI 搜索引擎框架&#xff0c;具有與 Perplexity.ai Pro 相同的性能。您可以輕松部署它來構建您自己的搜索引擎&#xff0c;可以使用閉源 LLM&#xff08;如 GPT、Claude…

Java高頻面試之并發編程-16

hello啊&#xff0c;各位觀眾姥爺們&#xff01;&#xff01;&#xff01;本baby今天又來報道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面試官&#xff1a;volatile 實現原理是什么&#xff1f; volatile 關鍵字的實現原理 volatile 是 Java 中用于解決多線程環境下變量可見性…

《零基礎學機器學習》學習大綱

《零基礎學機器學習》學習大綱 《零基礎學機器學習》采用對話體的形式&#xff0c;通過人物對話和故事講解機器學習知識&#xff0c;使內容生動有趣、通俗易懂&#xff0c;降低了學習門檻&#xff0c;豆瓣高分9.1分&#xff0c;作者權威。 接下來的數篇文章&#xff0c;我將用…

C# 中 static的使用

靜態(static)是C#中一個重要的關鍵字&#xff0c;它可以應用于類、方法、屬性和字段。 靜態類 靜態類的特點&#xff1a; 不能實例化只能包含靜態成員密封的&#xff08;sealed&#xff09;,不能被繼承 應用場景&#xff1a; 工具類/輔助類數學計算類&#xff1a;如Math類…

C++藍橋杯真題(題目+解析+流程圖)(特殊運算符+四葉玫瑰數+質因數的個數+最大的矩形紙片+數字游戲+活動人數)

C++藍橋杯真題 藍橋杯省賽C++題目分析1. 特殊運算符題目描述輸入描述輸出描述輸入輸出樣例正確代碼錯誤代碼分析流程圖2. 四葉玫瑰數題目描述輸入描述輸出描述輸入輸出樣例正確代碼錯誤代碼分析流程圖3. 質因數的個數題目描述輸入描述輸出描述輸入輸出樣例正確代碼錯誤代碼分析…

MYSQL 索引與數據結構筆記

MYSQL 索引與數據結構筆記 文章目錄 MYSQL 索引與數據結構筆記1. B-Tree 與 B Tree 基礎對比一、B 樹的優勢二、B 樹的進一步優化三、綜合對比結論 2. MySQL 為何選擇 B Tree3. 索引使用示例與性能分析3.1 整數字段索引查詢3.2 字符字段索引查詢 4. 索引失效與類型轉換陷阱5. 小…

電路中的DGND、GROUND、GROUND_REF的區別,VREF、VCC、VDD、VEE和VSS的區別?

目錄 1 DGND、GROUND、GROUND_REF的區別 1.1 DGND&#xff08;Digital Ground&#xff09; 1.2 GROUND&#xff08;Ground&#xff09; 1.3 GROUND_REF&#xff08;Ground Reference&#xff09; 1.4 區別 2 VREF、VCC、VDD、VEE和VSS的區別 2.1 VREF&#xff08;Refere…

OpenHarmony平臺驅動開發(十),MMC

OpenHarmony平臺驅動開發&#xff08;十&#xff09; MMC 概述 功能簡介 MMC&#xff08;MultiMedia Card&#xff09;即多媒體卡&#xff0c;是一種用于固態非易失性存儲的小體積大容量的快閃存儲卡。 MMC后續泛指一個接口協定&#xff08;一種卡式&#xff09;&#xff0…

C++ 的 VS 項目中引入跨平臺包管理工具 conan

我們知道 C 不像很多其他語言有包管理工具&#xff0c;比如 Python 有 pip&#xff0c;Java 有 maven&#xff0c;C# 有 nuget&#xff0c;JS 有 npm&#xff0c;Go 有 go mod&#xff0c;Rust 有 cargo&#xff0c;項目中需要自己手動引入第三方庫&#xff0c;手動維護帶來了很…

vscode 默認環境路徑

1.下面放在項目根目錄上&#xff1a; .vscode/settings.json 2.settings.json內容&#xff1a; {"python.analysis.extraPaths": ["${workspaceFolder}"],"python.defaultInterpreterPath": "/shared_disk/users/lbg/envs/py310_see3d/b…

Android 項目中配置了多個 maven 倉庫,但依賴還是下載失敗,除了使用代理,還有其他方法嗎?

文章目錄 前言解決方案gradlemaven 倉庫 前言 我們在Android 開發的過程中&#xff0c;經常會遇到三方依賴下載不下來的問題。一般情況下我們會在項目的build.gradle文件中配置多個 maven 倉庫來解決。 // Top-level build file where you can add configuration options com…

uni-app 引入vconsole web端正常,安卓端報錯 Cannot read property ‘sendBeacon‘ of undefined

reportJSException >>>> exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->Uncaught TypeError: Cannot read property sendBeacon of undefined vconsole 只支持 web 端&#xff0c;…

火山RTC 7 獲得遠端裸數據

一、獲得遠端裸數據 1、獲得h264數據 1&#xff09;、遠端編碼后視頻數據監測器 /*** locale zh* type callback* region 視頻管理* brief 遠端編碼后視頻數據監測器<br>* 注意&#xff1a;回調函數是在 SDK 內部線程&#xff08;非 UI 線程&#xff09;同步拋出來的&a…

web 自動化之 Unittest 四大組件

文章目錄 一、如何開展自動化測試1、項目需求分析&#xff0c;了解業務需求 web 功能納入自動化測試2、選擇何種方式實現自動化測試 二、Unittest 框架三、TestCase 測試用例四、TestFixture 測試夾具 執行測試用例前的前置操作及后置操作五、TestSuite 測試套件 & TestLoa…

42、在.NET 中能夠將?靜態的?法覆寫成靜態?法嗎?

在.NET中&#xff0c;不能將非靜態方法&#xff08;實例方法&#xff09;直接覆寫&#xff08;Override&#xff09;為靜態方法&#xff08;Static Method&#xff09;。以下是關鍵原因和解釋&#xff1a; 1. 方法綁定的本質區別 實例方法&#xff1a;屬于對象的實例&#xf…

8天Python從入門到精通【itheima】-1~5

目錄 1節&#xff1a; 1.Python的優勢&#xff1a; 2.Python的獨具優勢的特點&#xff1a; 2節-初識Python&#xff1a; 1.Python的起源 2.Python廣泛的適用面&#xff1a; 3節-什么是編程語言&#xff1a; 1.編程語言的作用&#xff1a; 2.編程語言的好處&#xff1a;…

3D迷宮探險:偽3D渲染與運動控制的數學重構

目錄 3D迷宮探險:偽3D渲染與運動控制的數學重構引言第一章 偽3D渲染引擎1.1 射線投射原理1.2 紋理透視校正第二章 迷宮生成算法2.1 圖論生成模型2.2 復雜度控制第三章 第一人稱控制3.1 運動微分方程3.2 鼠標視角控制第四章 碰撞檢測優化4.1 層級檢測體系4.2 滑動響應算法第五章…

mac一鍵安裝gpt-sovit教程中,homebrew卡住不動的問題

mac一鍵安裝gpt-sovit教程 僅作為安裝過程中解決homebrew卡住問題的記錄 資源地址 https://www.yuque.com/baicaigongchang1145haoyuangong/ib3g1e/znoph9dtetg437xb#mlAoP 下載一鍵包 下載后并解壓&#xff0c;找到install for mac.sh&#xff0c;終端執行bash空格拖拽in…

git 遠程倉庫管理詳解

Git 的遠程倉庫管理是多人協作和代碼共享的核心功能。以下是 Git 遠程倉庫管理的詳細說明&#xff0c;包括常用操作、命令和最佳實踐。 1. 什么是遠程倉庫&#xff1f; 遠程倉庫&#xff08;Remote Repository&#xff09;&#xff1a;存儲在網絡服務器上的 Git 倉庫&#xff0…

【超詳細教程】安卓模擬器如何添加本地文件?音樂/照片/視頻一鍵導入!

作為一名安卓開發者或手游愛好者&#xff0c;安卓模擬器是我們日常工作和娛樂的重要工具。但很多新手在使用過程中常常遇到一個共同問題&#xff1a;**如何將電腦本地的音樂、照片、視頻等文件導入到安卓模擬器中&#xff1f;**今天&#xff0c;我將為大家帶來一份全網最詳細的…