5.2 使用Spring的验证器接口进行验证 {#toc_2}

Spring具有一个Validator接口可以让你用于验证对象。Validator接口在工作时需要使用一个Errors对象,以便于在验证过程中,验证器可以将验证失败的信息报告给这个Errors对象。

让我们考虑一个小的数据对象:

  1. public class Person {
  2. private String name;
  3. private int age;
  4. // the usual getters and setters...
  5. }

通过实现org.springframework.validation.Validator的下列两个接口,我们打算为Person类提供验证行为:

  • support(Class)– 这个Validator是否可以验证给定Class的实例validate(Object,org.springframework.validation.Errors)
  • – 验证给定的对象并且万一验证错误,可以将这些错误注册到给定的Errors对象

实现一个Validator是相当简单的,特别是当你知道Spring框架还提供了ValidationUtils辅助类:

  1. public class PersonValidator implements Validator {
  2. /**
  3. * This Validator validates *just* Person instances
  4. */
  5. public boolean supports(Class clazz) {
  6. return Person.class.equals(clazz);
  7. }
  8. public void validate(Object obj, Errors e) {
  9. ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
  10. Person p = (Person) obj;
  11. if (p.getAge() < 0) {
  12. e.rejectValue("age", "negativevalue");
  13. } else if (p.getAge() > 110) {
  14. e.rejectValue("age", "too.darn.old");
  15. }
  16. }
  17. }

正如你看到的,ValidationUtils类的静态方法rejectIfEmpty(..)被用于拒绝那些值为null或者空字符串的'name'属性。除了上面展示的例子之外,去看一看ValidationUtils的java文档有助于了解它提供的功能。

通过实现单个的Validator类来逐个验证富对象中的嵌套对象当然是有可能的,然而将验证逻辑封装在每个嵌套类对象自身的Validator实现中可能是一种更好的选择。Customer就是一个‘富’对象的简单示例,它由两个字符串属性(姓和名)以及一个复杂对象Address组成。Address对象可能独立于Customer对象使用,因此已经实现了一个独特的AddressValidator。如果你想要你的CustomerValidator不借助于复制粘贴而重用包含在AddressValidator中的逻辑,那么你可以通过依赖注入或者实例化你的CustomerValidator中的AddressValidator,然后像这样使用它:

  1. public class CustomerValidator implements Validator {
  2. private final Validator addressValidator;
  3. public CustomerValidator(Validator addressValidator) {
  4. if (addressValidator == null) {
  5. throw new IllegalArgumentException("The supplied [Validator] is " +
  6. "required and must not be null.");
  7. }
  8. if (!addressValidator.supports(Address.class)) {
  9. throw new IllegalArgumentException("The supplied [Validator] must " +
  10. "support the validation of [Address] instances.");
  11. }
  12. this.addressValidator = addressValidator;
  13. }
  14. /**
  15. * This Validator validates Customer instances, and any subclasses of Customer too
  16. */
  17. public boolean supports(Class clazz) {
  18. return Customer.class.isAssignableFrom(clazz);
  19. }
  20. public void validate(Object target, Errors errors) {
  21. ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required");
  22. ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required");
  23. Customer customer = (Customer) target;
  24. try {
  25. errors.pushNestedPath("address");
  26. ValidationUtils.invokeValidator(this.addressValidator, customer.getAddress(), errors);
  27. } finally {
  28. errors.popNestedPath();
  29. }
  30. }
  31. }

验证错误被报告给传递到验证器的Errors对象。在使用Spring Web MVC的情况下,你可以使用<spring:bind/>标签来检查错误信息,不过当然你也可以自己检查错误对象。有关它提供的方法的更多信息可以在java文档中找到。