跳到主要内容

使用 Spring 的 Validator 接口进行验证

ChatGPT-4o 中英对照 Validation by Using Spring’s Validator Interface

Spring 提供了一个 Validator 接口,你可以用来验证对象。Validator 接口通过使用 Errors 对象来工作,这样在验证时,验证器可以将验证失败报告给 Errors 对象。

考虑以下小数据对象的示例:

public class Person {

private String name;
private int age;

// the usual getters and setters...
}
java

下一个示例通过实现 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");
}
}
}
java

ValidationUtils 类中的 static 方法 rejectIfEmpty(..) 用于在 name 属性为 null 或空字符串时进行拒绝。查看 ValidationUtils javadoc,了解除了之前示例中展示的功能之外,它还提供了哪些功能。

虽然确实可以实现一个单一的 Validator 类来验证丰富对象中的每个嵌套对象,但将每个嵌套类对象的验证逻辑封装在其自己的 Validator 实现中可能更好。一个“丰富”对象的简单例子是一个由两个 String 属性(名字和姓氏)和一个复杂的 Address 对象组成的 CustomerAddress 对象可以独立于 Customer 对象使用,因此实现了一个独立的 AddressValidator。如果你希望在 CustomerValidator 中重用 AddressValidator 类中包含的逻辑,而不需要复制粘贴,你可以在 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();
}
}
}
java

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

验证器也可以在不涉及绑定过程的情况下本地调用,以立即验证给定对象。从 6.1 版本开始,通过一个新的 Validator.validateObject(Object) 方法简化了这一过程,该方法现在默认可用,返回一个简单的 Errors 表示,可以进行检查:通常调用 hasErrors() 或新的 failOnError 方法,将错误摘要消息转换为异常(例如,validator.validateObject(myObject).failOnError(IllegalArgumentException::new))。