首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Hibernate 能够满足我们的验证需求(3)对控制器添加验证

Hibernate 能够满足我们的验证需求(3)对控制器添加验证

要执行验证,需要创建一个 Hibernate 的 ClassValidator 实例。这个类进行实例化的代价可能会很高,因此最好只对希望进行验证的每个类来进行实例化。一种方法是创建一个实用工具类,对每个模型对象存储一个 ClassValidator 实例,如清单 4 所示:
清单 4. 处理验证的实用工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* Handles validations based on the Hibernate Annotations Validator framework.
* @author Ted Bergeron
* @version $Id: AnnotationValidator.java,v 1.5 2006/01/20 17:34:09 ted Exp $
*/
public class AnnotationValidator {
    private static Log log = LogFactory.getLog(AnnotationValidator.class);

    // It is considered a good practice to execute these lines once and
    // cache the validator instances.
    public static final ClassValidator<Customer> CUSTOMER_VALIDATOR =
       new ClassValidator<Customer>(Customer.class);
    public static final ClassValidator<CreditCard> CREDIT_CARD_VALIDATOR =
       new ClassValidator<CreditCard>(CreditCard.class);

    private static ClassValidator<? extends BaseObject> getValidator(Class<?
      extends BaseObject> clazz) {
        if (Customer.class.equals(clazz)) {
            return CUSTOMER_VALIDATOR;
        } else if (CreditCard.class.equals(clazz)) {
            return CREDIT_CARD_VALIDATOR;
        } else {
            throw new IllegalArgumentException("Unsupported class was passed.");
        }
    }

    public static InvalidValue[] getInvalidValues(BaseObject modelObject) {
        String nullProperty = null;
        return getInvalidValues(modelObject, nullProperty);
    }

    public static InvalidValue[] getInvalidValues(BaseObject modelObject,
       String property) {
        Class<? extends BaseObject>clazz = modelObject.getClass();
        ClassValidator validator = getValidator(clazz);

        InvalidValue[] validationMessages;

        if (property == null) {
            validationMessages = validator.getInvalidValues(modelObject);
        } else {
            // only get invalid values for specified property.  
            // For example, "city" applies to getCity() method.
            validationMessages = validator.getInvalidValues(modelObject, property);
        }
        return validationMessages;
    }
}




在清单 4 中,创建了两个 ClassValidator,一个用于 Customer,另外一个用于 CreditCard。这两个希望进行验证的类可以调用 getInvalidValues(BaseObject modelObject),会返回 InvalidValue[]。这则会返回一个包含模型对象实例错误的数组。另外,这个方法也可以通过提供一个特定的属性名来调用,这样做会只返回与该域有关的错误。
在使用 Spring MVC 和 Hibernate Validator 时,为信用卡创建一个验证过程变得非常简单,如清单 5 所示:
清单 5. Spring MVC 控制器使用的 CreditCardValidator
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* Performs validation of a CreditCard in Spring MVC.
*
* @author Ted Bergeron
* @version $Id: CreditCardValidator.java,v 1.2 2006/02/10 21:53:50 ted Exp $
*/
public class CreditCardValidator implements Validator {

    private CreditCardService creditCardService;

    public void setCreditCardService(CreditCardService service) {
        this.creditCardService = service;
    }

    public boolean supports(Class clazz) {
        return CreditCard.class.isAssignableFrom(clazz);
    }

    public void validate(Object object, Errors errors) {
        CreditCard creditCard = (CreditCard) object;

        InvalidValue[] invalids = AnnotationValidator.getInvalidValues(creditCard);
         
        // Perform "expensive" validation only if no simple errors found above.
        if (invalids == null || invalids.length == 0) {
            boolean validCard = creditCardService.validateCreditCard(creditCard);
            if (!validCard) {
                errors.reject("error.creditcard.invalid");
            }
        } else {
            for (InvalidValue invalidValue : invalids) {
                errors.rejectValue(invalidValue.getPropertyPath(),
                  null, invalidValue.getMessage());
            }
        }
    }
}




validate() 方法只需要将 creditCard 实例传递给这个验证过程,从而返回 InvalidValue 数组。如果发现了一个或多个这种简单错误,那么就可以将 Hibernate 的 InvalidValue 数组转换成 Spring 的 Errors 对象。如果用户已经创建了这个信用卡并且没有出现任何简单错误,就可以将更加彻底的验证委托给服务层进行。这一层可以与商业服务提供者一起对信用卡进行验证。
现在我们已经看到这个简单的模型层注释是如何平衡到控制器、DAO 和 DBMS 层的验证的。在 HibernateDoclet 和 Commons Validator 中发现的验证逻辑的重合现在都已经统一到模型中了。尽管这是一个非常受欢迎的改进,但是视图层传统上来说一直是最需要进行详细验证的地方。
返回列表