spring验证器Validator接口

spring2.0

Validator接口

Method Summary
boolean supports(Classclazz)
Can this Validator validate instances of the supplied clazz?
void validate(Objecttarget, Errorserrors)
Validate the supplied target object, which must be of a Class for which the supports(Class) method typically has (or would) return true.

<!-- ============ METHOD DETAIL ========== --><!-- -->

Method Detail
<!-- -->

supports

boolean supports(Classclazz)
Can this Validator validate instances of the supplied clazz?

This method is typically implemented like so:

return Foo.class.isAssignableFrom(clazz);
(Where Foo is the class (or superclass) of the actual object instance that is to be validated.)

Parameters:
clazz - the Class that this Validator is being asked if it can validate
Returns:
true if this Validator can indeed validate instances of the supplied clazz

<!-- -->

validate

void validate(Objecttarget,
              Errorserrors)
Validate the supplied target object, which must be of a Class for which the supports(Class) method typically has (or would) return true.

The supplied errors instance can be used to report any resulting validation errors.

Parameters:
target - the object that is to be validated (can be null)
errors - contextual state about the validation process (never null)
See Also:
ValidationUtils

<!-- ========= END OF CLASS DATA ========= -->spring中文开发文档
1. 简介
对是否把校验当作业务逻辑这个问题,存在着正和反两种意见,而Spring提供的验证模式(和数据绑定)的设计对这两种意见都不排斥。特别是,校验应该不应该被强制绑定在Web层,而且应该很容易本地化并且可以方便地加入新的验证逻辑。基于上述的考虑,Spring提供了一个Validator接口。这是一个基础的接口并且适用于应用程序的任何一个层面。

数据绑定(Data binding)非常有用,它可以动态把用户输入与应用程序的域模型(或者你用于处理用户输入的对象)绑定起来。Spring针对此提供了所谓的DataBinder来完成这一功能。由Validator和DataBinder组成的validation验证包,主要被用于Spring的MVC框架。当然,他们同样可以被用于其他需要的地方。

BeanWrapper作为一个基础组件被用在了Spring框架中的很多地方。不过,你可能很少会需要直接使用BeanWrapper。由于这是一篇参考文档,因而我们觉得对此稍作解释还是有必要的。我们在这一章节里对BeanWrapper的说明,或许到了你日后试图进行类似对象与数据之间的绑定这种与BeanWrapper非常相关的操作时会有一些帮助。

Spring大量地使用了PropertyEditor(属性编辑器)。PropertyEditor的概念是JavaBean规范的一部分。正如上面提到的BeanWrapper一样,由于它与BeanWrapper以及DataBinder三者之间有着密切的联系,我们在这里同样对PropertyEditor作一番解释。

2. 使用Spring的Validator接口进行校验

你可以使用Spring提供的validator接口进行对象的校验。Validator接口与Errors协同工作,在Spring做校验的时候,它会将所有的校验错误汇总到Errors对象中去。

来看这个简单的数据对象:

public class Person {

private String name;
private int age;

// the usual getters and setters...
}实现org.springframework.validation.Validator接口中的两个方法,我们将为对Person类加上校验行为:

supports(Class):表示这个Validator是否支持该Class的实例?

validate(Object, org.springframework.validation.Errors):对提供的对象进行校验,并将校验的错误注册到传入的Errors 对象中。


实现一个Validator也比较简单,尤其是当你学会了Spring所提供的ValidationUtils以后。我们一起来看一下如何才能创建一个校验器。

public class PersonValidator implements Validator {

/**
* This Validator validates just Person instances
*/
public boolean supports(Class clazz) {
return Person.class.equals(clazz);
}

public void validate(Object obj, Errors e) {
ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
Person p = (Person) obj;
if (p.getAge() < 0) {
e.rejectValue("age", "negativevalue");
} else if (p.getAge() > 110) {
e.rejectValue("age", "too.darn.old");
}
}
}
如你所见,我们使用了ValidationUtils中的一个静态方法rejectIfEmpty(..)来对name属性进行校验,假若'name'属性是 null 或者空字符串的话,就拒绝验证通过 。请参照ValidationUtils相关的JavaDoc,查看一下除了例子中介绍过的之外其他的一些功能。

对复杂对象来说,实现Validator类来验证其内置的属性类当然也是可行的,但是为每个内置类的示例实现Validator可能是个更好的主意。关于这样的一个'rich'这样的例子是Customer类,它包含两个String属性(first name 和second name),还有一个复杂的Address对象。Address对象可能独立于Customer对象,因此独立实现了一个AddressValidator。假若你希望你的CustomerValidator重用AddressValidator内部的逻辑,但是又不想通过拷贝粘贴来实现,你可以在你的CustomerValidator中依赖注入AddressValidator对象,或者创建一个。然后这样用:

public class CustomerValidator implements Validator {

private final Validator addressValidator;

public UserValidator(Validator addressValidator) {
if (addressValidator == null) {
throw new IllegalArgumentException("The supplied [Validator] is required and must not be null.");
}
if (!addressValidator.supports(Address.class)) {
throw new IllegalArgumentException(
"The supplied [Validator] must support the validation of [Address] instances.");
}
this.addressValidator = addressValidator;
}

/**
* This Validator validates Customer instances, and any subclasses of Customer too
*/
public boolean supports(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}

public void validate(Object target, Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
Customer customer = (Customer) target;
try {
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
} finally {
errors.popNestedPath();
}
}
}验证错误会被报告到传来的Errors对象中。在Spring Web MVC中,你可以使用<spring:bind/>标签来检查错误信息,当然你也可以自行处理错误。可以在它的Javadoc中找到它提供的方法的描述。

3. 从错误代码到错误信息
我们已经讨论了数据绑定和校验。最后我们来讨论一下与校验错误相对应的错误信息输出。在先前的示例中,我们对name和age字段进行了校验并发现了错误。如果我们想用MessageSource来输出错误信息,当某个字段校验出错时(在这个例子中是name和age)我们输出的是错误代码。无论你直接或者间接使用示例中的ValidationUtils 类来调用Errors接口中rejectValue方法或者任何一个其它的reject方法,底层的实现不仅为你注册了你传入的代码,还同时为你注册了许多额外的错误代码信息。而你使用的MessageCodesResolver将决定究竟注册什么样的错误代码。默认情况下,将会使用DefaultMessageCodesResolver。回到前面的例子,使用DefaultMessageCodesResolver,不仅会为你注册你提供的错误代码信息,同时还包含了你传入到reject方法中的字段信息。所以在这个例子中,你通过rejectValue("age", "too.darn.old")来注册一个字段校验错误。Spring不仅为你注册了too.darn.old这个代码,同时还为你注册了too.darn.old.age和too.darn.old.age.int来分别表示字段名称和字段的类型。这种是现实为了方面开发者来定位错误信息。

更多有关MessageCodesResolver的信息以及默认的策略可以在线访问相应的JavaDocs: MessageCodesResolver 和 DefaultMessageCodesResolver .

你可能感兴趣的:(设计模式,spring,框架,Web,mvc)