Spring Boot提供了spring-boot-starter-validation 為Bean的校驗提供支持。我們可以通過一系列的校驗注解對Java Bean的屬性進行校驗。
在Java世界里,用于Java Bean的校驗的標準規范是JSR 380,又被稱作Bean Validation 2.0。而JSR 380的實現是Hibernate Validator。
Spring Boot提供了spring-boot-starter-validation 為Bean的校驗提供支持。我們可以通過一系列的校驗注解對Java Bean的屬性進行校驗。
本文將演示如何在對Spring MVC的請求參數進行校驗。當然它可以用在任何Java Bean的校驗上。
我們先新建一個演示項目,注意除了添加“Spring Web”依賴,還需要額外添加“Validation”依賴,從Spring Boot 2.3后,我們需要顯示添加此依賴。

常用JSR 380注解及如何校驗請求DTO
@Data
public class PersonDto {
@NotNull(message = "姓名不能為空")
private String name;
@Min(value = 18, message = "年紀最小18")
@Max(value = 60, message = "年紀最大60")
private Integer age;
@Email(message = "地址只能郵件")
private String email;
}
在DTO這個JavaBean上使用JSR 380注解,主要的注解有:
- @NotNull :校驗注解的屬性不能為null
- @AssertTrue : 校驗注解的屬性是true
- @Size : 校驗大小范圍是在min和max之間,可以是String、Collection、Map,和數組屬性
- @Min: 校驗注解的屬性最小不能小于設定的值
- @Max: 校驗注解的屬性最大不能大于設定的值
- @Pattern:校驗當前字符串屬性符合指定的正則表達式
- @Email :校驗注解屬性是一個有效的郵件地址
- @NotEmpty:校驗注解的屬性不能為null或者是empty,以是String、Collection、Map,和數組屬性
- @NotBlank: 校驗文本屬性不為null或者空格
- @Positive 和 @PositiveOrZero :校驗整數是正數/正數或0
- @Negative 和 @NegativeOrZero :校驗整數是負數/負數或0
- @Past and @PastOrPresent :校驗日期是過去/過去或現在
- @Future and @FutureOrPresent :校驗日期是未來/未來或現在
注意上面的“message”中設置提示錯誤的信息。
控制器如何生效及如何校驗請求參數
@RestController
@RequestMapping("/people")
@Validated //2
public class PersonController {
@PostMapping
public String save(@Valid @RequestBody PersonDto personDto){ //1
return "OK";
}
@GetMapping("/findByAge") //2
public String findByAge(@Range(min = 18,max = 60, message = "年紀只能是18到60之間") Integer age){
return "OK";
}
}
1、校驗DTO,只需要在@RequestBody前加上注解“@Valid”,若出現校驗錯誤,拋出MethodArgumentNotValidException
2、檢驗請求中的參數(包括路徑變量),我們需要在類上注解“@Validated”才會生效,若出現校驗錯誤,拋出ConstraintViolationException。此處的@Range注解來自于Hibernate Validator,非標準JSR 380注解。
全局異常處理,給前端友好的校驗提示
當出現校驗錯誤時,Spring Boot只會拋出異常,所以為了讓前端更友好的處理這些異常,我們將對這些拋出的異常做出處理。
@RestControllerAdvice
public class CustomExceptionHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> validationExceptionHandler(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return errors;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(ConstraintViolationException.class)
public String validationExceptionHandler(ConstraintViolationException ex) {
return ex.getMessage();
}
}
驗證效果
運行應用,并違反校驗規則,如圖:


如何自定義檢驗注解
上面我們使用了JSR 380以及Hibernate的注解來校驗,這節我們演示如何自定義校驗注解。
我們通過定義個校驗注解“@Enumeration”和在“EnumerationValidator”類中定義校驗規則。
當前例子演示功能為:只能是枚舉里允許的值,否則校驗不通過。
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumerationValidator.class) //3
public @interface Enumeration {
String message() default "屬性只能從列表中來"; //1
String[] values(); //2
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
1、message屬性定義錯誤信息
2、values設置可選的枚舉值
3、通過“@Constraint”指定校驗的類
注意:若沒有groups()和payload(),會報:javax.validation.constraintdefinitionexception: hv000074
public class EnumerationValidator implements ConstraintValidator<Enumeration,String> {
private String message;
private List<String> allowable;
@Override
public void initialize(Enumeration enumeration){
this.message = enumeration.message();
this.allowable = Arrays.asList(enumeration.values());
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context){
return this.allowable.contains(value);
}
}
這里的邏輯很簡單,只需要可選的枚舉值包含被校驗的值即可。
- 控制器中,當然也配合了類上注解的“@Validated”
@GetMapping("/findByGender")
public String findByGender(@Enumeration(values = {"男","女"}, message = "性別只能是男或女") String gender){
return "OK";
}
啟動驗證結果:

感謝對我的書《從企業級開發到云原生微服務:Spring Boot實戰》的支持。
參考資料:
https://medium.com/codex/spring-boot-create-custom-annotation-to-validate-request-parameter-dcf483539d90
https://www.baeldung.com/spring-boot-bean-validation
https://reflectoring.io/bean-validation-with-spring-boot/
文章出自:??愛科學的衛斯理??,如有轉載本文請聯系愛科學的衛斯理今日頭條號。