使用 Infra Validator 接口进行验证
Infra 提供了一个 Validator 接口,您可以使用它来验证对象。
Validator 接口通过使用 Errors 对象工作,以便在验证时,验证器可以向 Errors 对象报告验证失败。
考虑以下一个简单数据对象的示例:
-
Java
public class Person {
private String name;
private int age;
// 通常的 getter 和 setter...
}
下一个示例通过实现 infra.validation.Validator 接口的以下两个方法,为 Person 类提供验证行为:
-
supports(Class): 此Validator可以验证提供的Class的实例吗? -
validate(Object, infra.validation.Errors): 验证给定对象,如果出现验证错误,则将其注册到给定的Errors对象中。
实现 Validator 相当简单,尤其是当您知道 TODAY Framework 还提供了 ValidationUtils 辅助类时。
以下示例为 Person 实例实现 Validator:
-
Java
public class PersonValidator implements Validator {
/**
* 此 Validator 仅验证 Person 实例
*/
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 类上的 static rejectIfEmpty(..) 方法用于在 name 属性为 null 或空字符串时拒绝它。
查看 ValidationUtils javadoc,
看看除了前面显示的示例之外,它还提供了什么功能。
虽然实现单个 Validator 类来验证丰富对象中的每个嵌套对象当然是可能的,
但最好将每个嵌套对象类的验证逻辑封装在其自己的 Validator 实现中。
“丰富”对象的一个简单示例是 Customer,它由两个 String 属性(名字和姓氏)和一个复杂的 Address 对象组成。
Address 对象可以独立于 Customer 对象使用,因此已经实现了独特的 AddressValidator。
如果您希望 CustomerValidator 重用包含在 AddressValidator 类中的逻辑而不诉诸复制和粘贴,
您可以在 CustomerValidator 中依赖注入或实例化一个 AddressValidator,如下例所示:
-
Java
public class CustomerValidator implements Validator {
private final Validator addressValidator;
public CustomerValidator(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;
}
/**
* 此 Validator 验证 Customer 实例,以及 Customer 的任何子类
*/
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 对象。在 Infra Web MVC 的情况下,
您可以使用 <spring:bind/> 标记来检查错误消息,但您也可以自己检查 Errors 对象。
有关其提供的方法的更多信息,请参阅 javadoc。
验证器也可以在本地调用以立即验证给定对象,而不涉及绑定过程。
从 5.0 开始,通过默认可用的新 Validator.validateObject(Object) 方法简化了这一点,
该方法返回一个可以检查的简单 Errors 表示:通常调用 hasErrors() 或新的 failOnError 方法
将错误摘要消息转换为异常(例如 validator.validateObject(myObject).failOnError(IllegalArgumentException::new))。