此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

使用 Spring 的验证器接口进行验证

Spring 具有Validator可用于验证对象的接口。这Validator接口的工作原理是使用Errors对象,以便在验证时, 验证者可以向Errors对象。spring-doc.cadn.net.cn

考虑以下小数据对象的示例:spring-doc.cadn.net.cn

public class Person {

	private String name;
	private int age;

	// the usual getters and setters...
}
class Person(val name: String, val age: Int)

下一个示例提供了Person类通过实现 以下两种方法org.springframework.validation.Validator接口:spring-doc.cadn.net.cn

  • supports(Class):可以这样吗Validator验证提供的实例Class?spring-doc.cadn.net.cn

  • validate(Object, org.springframework.validation.Errors):验证给定对象 并且,如果出现验证错误,则将这些错误与给定的Errors对象。spring-doc.cadn.net.cn

实现Validator相当简单,尤其是当您知道ValidationUtilsSpring Framework 也提供的 helper 类。以下内容 示例机具ValidatorPerson实例:spring-doc.cadn.net.cn

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");
		}
	}
}
class PersonValidator : Validator {

	/**
	 * This Validator validates only Person instances
	 */
	override fun supports(clazz: Class<*>): Boolean {
		return Person::class.java == clazz
	}

	override fun validate(obj: Any, e: Errors) {
		ValidationUtils.rejectIfEmpty(e, "name", "name.empty")
		val p = obj as Person
		if (p.age < 0) {
			e.rejectValue("age", "negativevalue")
		} else if (p.age > 110) {
			e.rejectValue("age", "too.darn.old")
		}
	}
}

static rejectIfEmpty(..)方法ValidationUtilsclass 用于 拒绝name属性(如果是)null或空字符串。看看ValidationUtilsJava文档 查看除了前面显示的示例之外,它还提供哪些功能。spring-doc.cadn.net.cn

虽然当然可以实现单个Validator类来验证每个 对于富对象中的嵌套对象,封装验证可能更好 逻辑Validator实现。一个简单的 “丰富”对象的示例是Customer由两个组成String属性(名字和第二个名字)和复合体Address对象。Address对象 可以独立使用Customer对象,因此AddressValidator已经实施。如果你想要你的CustomerValidator重用包含的逻辑 在AddressValidator类,无需诉诸复制和粘贴,您可以 dependency-inject 或实例化AddressValidator在您的CustomerValidator, 如以下示例所示:spring-doc.cadn.net.cn

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();
		}
	}
}
class CustomerValidator(private val addressValidator: Validator) : Validator {

	init {
		if (addressValidator == null) {
			throw IllegalArgumentException("The supplied [Validator] is required and must not be null.")
		}
		if (!addressValidator.supports(Address::class.java)) {
			throw IllegalArgumentException("The supplied [Validator] must support the validation of [Address] instances.")
		}
	}

	/*
	* This Validator validates Customer instances, and any subclasses of Customer too
	*/
	override fun supports(clazz: Class<>): Boolean {
		return Customer::class.java.isAssignableFrom(clazz)
	}

	override fun validate(target: Any, errors: Errors) {
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "field.required")
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "surname", "field.required")
		val customer = target as Customer
		try {
			errors.pushNestedPath("address")
			ValidationUtils.invokeValidator(this.addressValidator, customer.address, errors)
		} finally {
			errors.popNestedPath()
		}
	}
}

验证错误将报告给Errors对象传递给验证者。在这种情况下 Spring Web MVC 的 MVC,您可以使用<spring:bind/>标记来检查错误消息,但 您还可以检查Errors反对自己。有关 它提供的方法可以在 JavaDoc 中找到。spring-doc.cadn.net.cn

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