[译]SpringMVC自定义验证注解(SpringMVC custom validation annotations)

在基于SpringMVC框架的开发中,我们经常要对用户提交的字段进行合法性验证,比如整数类型的字段有个范围约束,我们会用@Range(min=1, max=4)。在实际应用开发中,我们经常碰到一些自己业务的场景要自定义一些验证规则,而这是标准的JSR-303Hibernate Validation所不具备的,所以我们就要根据JSR-303的规范来扩展我们自定义的验证规则注释.

假设我们现在有个接口要接收一个手机的字段, 它的约束规则是13位数字字符. 我们可以通过正则表达式完成: ^d{13}$来验证. 下面是个javabean代码:

public class Person{
    @Phone
    private String phone;
}

我们再来看下@Phone的代码.

@Documented
@Constraint(validatedBy = PhoneConstraintValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
	String message() default "{Phone}";
	Class<?>[] groups() default {};
	Class<? extends Payload>[] payload() default {};
}

这个注解类看起来复杂, 其实不然. 因为这基本上每个扩展验证注解都必需定义的三个方法, 是规范定义的, 所以我们可以像个模板一样copy过来改下. 这里要注意的是这个message方法, 定义了如果验证出错时要显示的消息内容. 对于消息格式和规范, 可以使用标准的Spring Message Resource Bindle来, 可以参考这篇. 现在定义了注解, 正如你所料, 我们要定义下具体的业务规则:

public class PhoneConstraintValidator implements ConstraintValidator<Phone, String> {

	@Override
	public void initialize(Phone phone) { }

	@Override
	public boolean isValid(String phoneField, ConstraintValidatorContext cxt) {
		if(phoneField == null) {
			return false;
		}
		return phoneField.matches("^d{13}$");
	}
}

所有验证规则方法类都要实现ConstraintValidator<V,F>这个接口, 里面第一个方法initialize的参数是所关联的注解对象, 所以这个方法里可以取出使用注解的地方传进来的值, 后面一个例子会讲到这一点. 第二个最核心的方法isValid第一个参数就是我们要验证的字段值, 大家看下上面的代码就知道怎样使用了.

下面我们来看第二种形式的注解. 假如我们对用户的生日字段进行验证, 限制只满足1989年出生的人。 如下:

public class Person {
	@Year(1989)
	private Date birthday;

    // getters setters ...

}

现在自定义验证注解Year有要传入一个参数, 用默认的value方法接收:

@Documented
@Constraint(validatedBy = YearConstraintValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Year {

	int value();

	String message() default "{Year}";

	Class<?>[] groups() default {};

	Class<? extends Payload>[] payload() default {};

}

还是要上面的一样, 要定义一个规则约束描述类:

public class YearConstraintValidator implements ConstraintValidator<Year, Date> {

	private int annotationYear;

	@Override
	public void initialize(Year year) {
		this.annotationYear = year.value();
	}

	@Override
	public boolean isValid(Date target, ConstraintValidatorContext cxt) {
		if(target == null) {
			return true;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(target);
		int fieldYear = c.get(Calendar.YEAR);
		return fieldYear == annotationYear;
	}

}

可以看到initiallize方法中可以接收关联的注解Year, 这里可以取出里面的参数信息用于约束规则方法调用.

原文: http://www.javacodegeeks.com/2013/07/spring-mvc-custom-validation-annotations.html

原文地址:https://www.cnblogs.com/jcli/p/4050447.html