在开发过程中经常会遇到对客户端传输过来的数据进行验证,传入的数据不是数字类型,传入的身份证信息格式不对,等等。
之前是通过工具类来一个判断,那么显然这种方法就有些笨拙了,那么在Spring中 我们如何优雅的来处理这些问题?
对于Valication 这块,Spring 大体有两种机制。
一种是Spring的:org.springframework.validation.Validator
另一种是Spring 对JSR-303 Bean Validation API的集成了:javax.validation.Validator
这里我们主要讨论一下第二种。
首先我们来看一下Spring对数据验证的具体做法,这里引用一个官方实例来进行说明:
Foo target = new Foo();
DataBinder binder = new DataBinder(target);
// 添加验证器
binder.setValidator(new FooValidator());
// 将请求参数绑定到Foo类上
binder.bind(propertyValues);
// 数据验证
binder.validate();
// 获得验证结果
BindingResult results = binder.getBindingResult();
// result.getFieldError();
在控制器(@Controller)中我们可以使用如下方式开启验证。
public void companySignup(@Valid UserForm userForm,BindingResult result){
if (result.hasErrors()) {
//开始处理错误
FieldError error = result.getFieldError();
}
}
对于规范中内置的一些实用验证 可以引入Hibernate Validator 的实现。
以下为出几个内置注解
@AssertFalse(message = "暂未开通海外业务")
//message 中的信息可以在BindingResult中获得private Boolean foreigner;
@Min(value=10)private int income;
@Past
//时间必须是之前的
private Date birthday;
@NotNullpublic String remark;
@Pattern(regexp = "^[1][3,4,5,7,8][0-9]{9}$")
public String mobilePhone;
@Size(min = 6,max = 30)
public String name;
有内置当然就允许自定义了,那么我们来看一下自定义的验证器怎么来实现。
自定义验证比较简单,主要就是定义一个验证约束就可以了。
一个验证约束注解及对应的处理类。
我们就已验证身份证来进行设计,假设我们的用户分成了两类群体,一类是身份证群体,一类是护照群体。
其性质来看都属于身份认证,但验证手段有所不同。
约束注解
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
//这行注解 标识此注解式一个验证约束注解,需要绑定一个能处理该约束的处理器 这里用了IdcardConstraintor
@Constraint(validatedBy =IdcardConstraintor.class)
public @interface IdcardCheck {
/**
* 以下三个 是 自定义验证约束必需实现的方法
*/
String message() default "";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
/**
* 这个属性来确定是验证类型 [身份证,护照]
*/
IdcardType type() default IdcardType.ID;
enum IdcardType{
ID,PASSPORT
}
}
约束注解对应的处理器:
public class IdcardConstraintor implements ConstraintValidator<IdcardCheck,String> {
private IdcardCheck.IdcardType type;
/**
* Spring 会为每个使用了@IdcardCheck的字段对应一个实例,即处理器不是单例的。
* 所以可以在这里进行一些 初始化操作
*/
@Override
public void initialize(IdcardCheck idcardCheck) {
this.type = idcardCheck.type();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (this.type == IdcardCheck.IdcardType.ID) {
return IdcardUtils.verifyID(value);
}
else if(this.type == IdcardCheck.IdcardType.PASSPORT){
return IdcardUtils.verifyPassword(value);
}
throw new IllegalArgumentException(type + " can't find a handler");
}
}
OK 接收form类上面就可以进行使用了:
public class UserForm {
private String username;
@Email
//该注解式Hibernate实现里面内带的
private String email;
@Pattern(regexp = "^[1][3,4,5,7,8][0-9]{9}$",message = "It is not a valid mobile phone")
private String mobilePhone;
private String password;
@IdcardCheck(type = IdcardCheck.IdcardType.ID)
private String idcard;
}
OK 这样自定义的验证 就可以投入使用了,最后粘贴一下可能会用到的maven 信息
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.0.Final</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>