Hibernate 能够满足我们的验证需求(3)对控制器添加验证
- UID
- 1066743
|
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 控制器使用的 CreditCardValidator1
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 中发现的验证逻辑的重合现在都已经统一到模型中了。尽管这是一个非常受欢迎的改进,但是视图层传统上来说一直是最需要进行详细验证的地方。 |
|
|
|
|
|