跳到主要内容
版本:7.0.3

使用Spring的Validator接口进行验证

Hunyuan 7b 中英对照 Validation Using Spring’s Validator Interface

Spring 提供了一个 Validator 接口,你可以使用它来验证对象。Validator 接口通过使用一个 Errors 对象来工作,这样在验证过程中,验证器可以将验证失败的信息报告给 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这个辅助类时。以下示例为Person实例实现了Validator

public class PersonValidator implements Validator {

/**
* This Validator validates only 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 类中的 static rejectIfEmpty(..) 方法用于在 name 属性为 null 或空字符串时拒绝该属性的验证。请查看 ValidationUtils 的 Javadoc,了解除了前面展示的示例之外,该方法还提供了哪些功能。

虽然确实可以实现一个单一的Validator类来验证嵌套对象中的每一个对象,但更好的做法是将每个嵌套类的验证逻辑封装在其自己的Validator实现中。一个“复杂”对象的简单示例是Customer,它由两个String属性(名字和姓氏)和一个复杂的Address对象组成。Address对象可以独立于Customer对象使用,因此已经实现了一个独立的AddressValidator。如果你希望CustomerValidator能够重用AddressValidator类中的逻辑而无需复制粘贴,你可以使用依赖注入(dependency-injection)或者在CustomerValidator内部实例化一个AddressValidator,如下例所示:

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;
}

/**
* 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/> 标签来查看错误信息,但你也可以直接检查 Errors 对象本身。有关该对象提供的方法的更多信息,可以在 javadoc 中找到。

验证器也可以被本地调用,用于对给定对象进行即时验证,而无需经过绑定过程。从 6.1 版本开始,这一功能通过新的 Validator.validateObject(Object) 方法得到了简化,该方法现在默认可用,它返回一个简单的 Errors 表示形式,可以对其进行检查:通常调用 hasErrors() 或新的 failOnError 方法将错误摘要信息转换为异常(例如,validator.validateObject(myObject).failOnError(IllegalArgumentException::new))。