在Spring MVC中使用validator功能简化编码:
配置验证器
如果想要开启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> 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`!#$%^&*'{}?/+=|" +
"_~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?)+(\\.[a-z0-9]" +
"([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
{
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 之间