如何在Spring Boot 項目中自定義 Validation 注解
在Spring Boot項目中自定義Validation注解,可按以下步驟實現(xiàn),以手機號格式校驗(支持多地區(qū))為例:
一、定義自定義注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.PARAMETER}) // 作用于字段和方法參數(shù)
@Retention(RetentionPolicy.RUNTIME) // 運行時生效
@Constraint(validatedBy = PhoneValidator.class) // 關(guān)聯(lián)校驗器
public @interface Phone {
String message() default "手機號格式錯誤"; // 錯誤提示
Class<?>[] groups() default {}; // 分組校驗(如新增、更新)
Class<? extends Payload>[] payload() default {}; // 負(fù)載信息(可選)
String region() default "CN"; // 自定義屬性:地區(qū)(默認(rèn)中國)
}二、實現(xiàn)校驗邏輯(ConstraintValidator)
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class PhoneValidator implements ConstraintValidator<Phone, String> {
private String region; // 存儲注解的region屬性
@Override
public void initialize(Phone constraintAnnotation) {
this.region = constraintAnnotation.region(); // 初始化,獲取地區(qū)配置
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) return true; // 允許為空(若必填需額外處理,如@NotBlank配合使用)
// 根據(jù)地區(qū)校驗格式
switch (region) {
case "CN": // 中國手機號:11位,以1開頭,第二位3-9
return value.matches("^1[3-9]\\d{9}$");
case "US": // 美國手機號:+1開頭,后跟10位數(shù)字
return value.matches("^\\+1\\d{10}$");
default:
return false; // 未知地區(qū),校驗失敗
}
}
}三、應(yīng)用自定義注解
1. 在DTO中使用
public class UserDTO {
@NotBlank
private String username;
@Phone(region = "CN") // 校驗中國手機號
private String phone;
// 若需校驗美國手機號,可設(shè)置region="US"
// @Phone(region = "US")
// private String usPhone;
// getters/setters
}2. 在Controller中觸發(fā)校驗
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
public class UserController {
@PostMapping("/register")
public String register(@Validated @RequestBody UserDTO dto) {
// 校驗通過,執(zhí)行注冊邏輯
return "注冊成功";
}
}四、處理校驗異常(全局異常處理器)
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationError(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
StringBuilder errorMsg = new StringBuilder();
for (FieldError error : result.getFieldErrors()) {
errorMsg.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; ");
}
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(new ErrorResponse(HttpStatus.BAD_REQUEST.value(), errorMsg.toString()));
}
static class ErrorResponse {
private int code;
private String message;
public ErrorResponse(int code, String message) {
this.code = code;
this.message = message;
}
// getters
}
}五、擴展功能
1. 分組校驗(如新增和更新場景)
// 定義分組接口
public interface CreateGroup {}
public interface UpdateGroup {}
// 在DTO中指定分組
@Phone(region = "CN", groups = CreateGroup.class) // 新增時校驗手機號
private String phone;
// Controller中使用分組
@PostMapping("/create")
public String create(@Validated(CreateGroup.class) @RequestBody UserDTO dto) { ... }
@PutMapping("/update")
public String update(@Validated(UpdateGroup.class) @RequestBody UserDTO dto) { ... }2. 國際化錯誤消息
在src/main/resources下創(chuàng)建ValidationMessages.properties:
Phone.message=手機號格式錯誤(中文) Phone.message_en=Invalid phone number format(英文)
Spring Boot會根據(jù)Accept-Language頭自動匹配語言。
3. 復(fù)雜業(yè)務(wù)校驗(如手機號唯一性)
// 校驗器中注入Service(需將校驗器標(biāo)記為@Component,由Spring管理)
@Component
public class PhoneValidator implements ConstraintValidator<Phone, String> {
@Autowired
private UserService userService; // 假設(shè)UserService提供手機號唯一性查詢
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 先校驗格式,再校驗唯一性
if (!isFormatValid(value)) return false;
return !userService.existsByPhone(value); // 假設(shè)existsByPhone查詢數(shù)據(jù)庫
}
private boolean isFormatValid(String value) {
// 復(fù)用之前的格式校驗邏輯
return value.matches("^1[3-9]\\d{9}$");
}
}六、驗證效果
- 合法請求:
phone=13812345678,校驗通過,正常處理。 - 非法請求:
phone=123(格式錯誤),返回:{ "code": 400, "message": "phone: 手機號格式錯誤; " }
總結(jié)
自定義Validation注解的關(guān)鍵步驟為:
- 定義注解:通過
@Constraint關(guān)聯(lián)校驗器,設(shè)置屬性(如地區(qū)、錯誤消息)。 - 實現(xiàn)校驗邏輯:在
ConstraintValidator中編寫具體規(guī)則(格式、唯一性等)。 - 應(yīng)用注解:在DTO/參數(shù)上標(biāo)注,結(jié)合
@Validated觸發(fā)校驗。 - 處理異常:通過全局異常處理器返回標(biāo)準(zhǔn)化錯誤,提升用戶體驗。
這種方式可靈活擴展Spring Boot的校驗?zāi)芰Γ瑵M足復(fù)雜業(yè)務(wù)需求(如多地區(qū)格式、業(yè)務(wù)規(guī)則校驗),確保輸入數(shù)據(jù)的合法性,是微服務(wù)架構(gòu)中參數(shù)校驗的重要實踐。
到此這篇關(guān)于聊一聊在 Spring Boot 項目中自定義 Validation 注解的文章就介紹到這了,更多相關(guān)Spring Boot 自定義 Validation 注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Java中spring boot validation自定義注解使用方式
- SpringBoot使用Validation包進(jìn)行輸入?yún)?shù)校驗
- SpringBoot Validation入?yún)⑿r瀲H化的項目實踐
- spring?boot?validation參數(shù)校驗與分組嵌套各種類型及使用小結(jié)
- springboot中使用Hibernate-Validation校驗參數(shù)詳解
- SpringBoot使用Validation進(jìn)行參數(shù)校驗的示例詳解
- Spring?Boot之Validation自定義實現(xiàn)方式的總結(jié)
- spring-boot-starter-validation?校驗參數(shù)的實現(xiàn)
- SpringBoot之groups應(yīng)對不同的Validation規(guī)則自定義方式
相關(guān)文章
Java中將UUID存儲為Base64字符串的方法實現(xiàn)
使用Base64編碼來對UUID存儲在一些特定的場合被廣泛的使用,本文主要介紹了Java中將UUID存儲為Base64字符串的方法實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-04-04
Spring?Boot整合Log4j2.xml的問題及解決方法
這篇文章主要介紹了Spring?Boot整合Log4j2.xml的問題,本文給大家分享解決方案,需要的朋友可以參考下2023-09-09
Java封裝數(shù)組之改進(jìn)為泛型數(shù)組操作詳解
這篇文章主要介紹了Java封裝數(shù)組之改進(jìn)為泛型數(shù)組操作,結(jié)合實例形式詳細(xì)分析了Java封裝數(shù)組為泛型數(shù)組相關(guān)原理、操作技巧與注意事項,需要的朋友可以參考下2020-03-03
SpringBoot、Java 使用 Jsoup 解析 HTML 頁面
這篇文章主要介紹了SpringBoot、Java 使用 Jsoup 解析 HTML 頁面的詳細(xì)步驟,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08
java中使用try-catch-finally一些值得注意的事(必看)
下面小編就為大家?guī)硪黄猨ava中使用try-catch-finally一些值得注意的事(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-08-08

