<!-- JSR303 Validator定義 -->
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
</beans>
如果想要開啓Spring Framework的檢驗功能,需要定義一個驗證器Bean —>LocalValidatorFactoryBean
@Bean
public Validator getValidator()
{
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(this.messageSource());//支持國際化的錯誤信息
validator.setProviderClass(HibernateValidator.class);//指定驗證器實現的提供方
return validator;
}
JSR和Hibernate validator的校驗只能對Object的屬性(也就是Bean的域)進行校驗,不能對單個的參數進行校驗。
spring 在此基礎上進行了擴展,添加了MethodValidationPostProcessor攔截器,可以實現對方法參數的校驗
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor()
{
MethodValidationPostProcessor processor =
new MethodValidationPostProcessor();
processor.setValidator(this.localValidatorFactoryBean());
return processor;
}
在Springboot中會自動導入這兩個Bean,除非需要對Bean做定製,否則不需要顯示的定義這兩個Bean。
驗證POJO
被驗證的實體類
public class Foo {
@NotBlank
private String name;
@Min(18)
private Integer age;
@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手機號碼格式錯誤")
@NotBlank(message = "手機號碼不能爲空")
private String phone;
@Email(message = "郵箱格式錯誤")
private String email;
//... getter setter
}
驗證數據
public void myMethod1(@Validated Foo foo,BindingResult bingingResult)
{
if(bingingResult.hasErrors)
{
for(FieldError fieldError : bingingResult.getFieldErrors)
{
…
}
}
}
被@Validated註解的對象爲待驗證的對象,BindingResult爲驗證後存放的信息。每個Validated對應一個bindingResult
BingdingResult會被spring的驗證器自動填充,如果有錯誤,bingingResult.hasErrors的返回值會是true
基於方法進行校驗
在類前加上@Validated,在方法前加上需要驗證的註解–>對函數返回值進行校驗,在方法的傳入參數上加上需要驗證的註解—>對函數傳參進行校驗。
可以在傳入參數中加入BindingResult,捕獲校驗的結果。
也可以定義異常處理方法,捕獲驗證未通過拋出的異常
@RestController
@Validated
public class BarController {
@RequestMapping("/bar")
public @NotBlank String bar(@Min(18) Integer age) {
System.out.println("age : " + age);
return "";
}
@ExceptionHandler(ConstraintViolationException.class)
public Map handleConstraintViolationException(ConstraintViolationException cve){
Set<ConstraintViolation<?>> cves = cve.getConstraintViolations();
for (ConstraintViolation<?> constraintViolation : cves) {
System.out.println(constraintViolation.getMessage());
}
Map map = new HashMap();
map.put("errorCode",500);
return map;
}
}
編寫自己的校驗類型
編寫自定義的校驗註解
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {xxx.class})
@Pattern(regexp = “^[a-z0-9!#$%^&*'{}?/+=|_~-]+(\\.[a-z0-9
!#”, flags = {Pattern.Flag.CASE_INSENSITIVE})
@ReportAsSingleViolation
public @interface Email
{
String message() default “”;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
static @interface List {
Email[] value();
}
}
@Constraint註解是定義校驗註解必備的註解,其中屬性validatedBy中可以填寫指定的檢驗器類型,@Pattern是繼承的其他註解,@ReportAsSingleViolation表示這個註解會和@pattern註解組合在一起,只引發一次錯誤。
有時候,需要自定義校驗器校驗指定類型的註解,則需要編寫自己的校驗器。編寫自己的校驗器需要實現標準的校驗器接口ConstraintValidator。第一個泛型是校驗註解,第二個泛型是需要校驗的類型。
public class xxx.class implements ConstraintValidator<Email,CharSequence>
{
public void initialize(NotBlank annotation){…}
public boolean isValid(CharSequence value, ConstraintValidatorContext context){…}
}
附:
@Null:限制只能爲null
@NotNull:限制必須不能爲空
@AssertFalse 限制必須爲false
@AssertTrue 限制必須爲true
@DecimalMax(value) 限制必須爲一個不大於指定值得數字
@DecimalMax(value)限制必須爲一個不小於指定值得數字
@Digits(integer,fraction)限制必須爲一個小數,且整數部分的位數不能超過integer,小數部分不能超過fraction
@Futrue 限制必須爲一個將來的日期
@Max(value) 限制必須爲一個不大於指定值得數字
@Min(value)限制必須爲一個不小於指定值得數字
@Past限制必須爲一個過去的時間
@Pattern(value)限制爲符合指定的正則表達式
@Size(max,min)限制字符長度在min 到 max 之間