对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

Java Bean验证

Spring框架为 Java Bean验证 API提供了支持。spring-doc.cadn.net.cn

Bean验证概述

Bean Validation 通过约束声明和元数据为 Java 应用程序提供了一种通用的验证方式。要使用它,你可以通过声明性验证约束对领域模型属性进行注解,然后由运行时进行强制执行。有内置的约束,你也可以定义自己的自定义约束。spring-doc.cadn.net.cn

考虑以下示例,它显示了一个带有两个属性的简单 PersonForm 模型:spring-doc.cadn.net.cn

public class PersonForm {
	private String name;
	private int age;
}
class PersonForm(
		private val name: String,
		private val age: Int
)

Bean Validation 允许您如以下示例所示声明约束:spring-doc.cadn.net.cn

public class PersonForm {

	@NotNull
	@Size(max=64)
	private String name;

	@Min(0)
	private int age;
}
class PersonForm(
	@get:NotNull @get:Size(max=64)
	private val name: String,
	@get:Min(0)
	private val age: Int
)

一个 Bean Validation 验证器会根据声明的约束来验证此类的实例。有关 API 的一般信息,请参阅 Bean Validation。有关特定约束的信息,请参阅 Hibernate Validator 文档。要了解如何将 bean 验证提供程序设置为 Spring bean,请继续阅读。spring-doc.cadn.net.cn

配置Bean验证提供程序

Spring 为 Bean Validation API 提供了完整的支持,包括将 Bean Validation 提供者作为 Spring bean 进行引导。这使您可以在应用程序中需要验证的任何位置注入 jakarta.validation.ValidatorFactoryjakarta.validation.Validatorspring-doc.cadn.net.cn

您可以使用 LocalValidatorFactoryBean 将默认的 Validator 配置为 Spring bean,如下例所示:spring-doc.cadn.net.cn

import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class AppConfig {

	@Bean
	public LocalValidatorFactoryBean validator() {
		return new LocalValidatorFactoryBean();
	}
}
<bean id="validator"
	class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

前面示例中的基本配置通过使用其默认的引导机制来触发 bean 验证的初始化。类路径中应存在一个 Bean 验证提供程序,例如 Hibernate Validator,并且会自动检测到它。spring-doc.cadn.net.cn

注入验证器

LocalValidatorFactoryBean 同时实现 jakarta.validation.ValidatorFactoryjakarta.validation.Validator,以及 Spring 的 org.springframework.validation.Validator。 您可以将对这两个接口之一的引用注入到需要调用验证逻辑的 bean 中。spring-doc.cadn.net.cn

您可以注入对 jakarta.validation.Validator 的引用,如果您希望直接使用 Bean 验证 API,如下例所示:spring-doc.cadn.net.cn

import jakarta.validation.Validator;

@Service
public class MyService {

	@Autowired
	private Validator validator;
}
import jakarta.validation.Validator;

@Service
class MyService(@Autowired private val validator: Validator)

如果您的 bean 需要 Spring 验证 API,您可以注入对 org.springframework.validation.Validator 的引用,如下例所示:spring-doc.cadn.net.cn

import org.springframework.validation.Validator;

@Service
public class MyService {

	@Autowired
	private Validator validator;
}
import org.springframework.validation.Validator

@Service
class MyService(@Autowired private val validator: Validator)

配置自定义约束

每个 bean 验证约束由两部分组成:spring-doc.cadn.net.cn

  • 一个 @Constraint 注解,用于声明约束及其可配置的属性。spring-doc.cadn.net.cn

  • 对实现 jakarta.validation.ConstraintValidator 接口的实现,该实现实现了约束的行为。spring-doc.cadn.net.cn

要将声明与实现相关联,每个 @Constraint 注解都引用一个相应的 ConstraintValidator 实现类。在运行时,当在您的领域模型中遇到约束注解时,ConstraintValidatorFactory 会实例化所引用的实现类。spring-doc.cadn.net.cn

默认情况下,LocalValidatorFactoryBean 配置了一个使用 Spring 创建 SpringConstraintValidatorFactory 实例的 ConstraintValidator。这使得您的自定义 ConstraintValidators 能够像其他 Spring bean 一样受益于依赖注入。spring-doc.cadn.net.cn

以下示例显示了一个自定义 @Constraint 声明,后跟一个使用 Spring 进行依赖注入的关联 ConstraintValidator 实现:spring-doc.cadn.net.cn

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=MyConstraintValidator.class)
public @interface MyConstraint {
}
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@Constraint(validatedBy = MyConstraintValidator::class)
annotation class MyConstraint
import jakarta.validation.ConstraintValidator;

public class MyConstraintValidator implements ConstraintValidator {

	@Autowired;
	private Foo aDependency;

	// ...
}
import jakarta.validation.ConstraintValidator

class MyConstraintValidator(private val aDependency: Foo) : ConstraintValidator {

	// ...
}

如前面的示例所示,一个 ConstraintValidator 实现可以将其依赖项 @Autowired 作为任何其他 Spring Bean。spring-doc.cadn.net.cn

基于Spring的方法验证

您可以通过MethodValidationPostProcessor bean 定义将 Bean Validation 1.1(以及作为自定义扩展的 Hibernate Validator 4.3)支持的方法验证功能集成到 Spring 上下文中:spring-doc.cadn.net.cn

import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

@Configuration
public class AppConfig {

	@Bean
	public MethodValidationPostProcessor validationPostProcessor() {
		return new MethodValidationPostProcessor();
	}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>

要符合Spring驱动的方法验证条件,所有目标类都需要使用Spring的@Validated注解进行标注,该注解还可以选择性地声明要使用的验证组。有关与Hibernate Validator和Bean Validation 1.1提供程序的设置详情,请参见 MethodValidationPostProcessorspring-doc.cadn.net.cn

方法验证依赖于目标类周围的AOP代理,对于接口上的方法,使用JDK动态代理或CGLIB代理。 使用代理时有一些限制,其中一些在理解AOP代理中进行了描述。此外,请记住始终使用代理类上的方法和访问器;直接字段访问将不起作用。spring-doc.cadn.net.cn

其他配置选项

默认的 LocalValidatorFactoryBean 配置对于大多数情况来说已经足够。有许多配置选项可用于各种 Bean Validation 构造,从消息插值到遍历解析。有关这些选项的更多信息,请参阅 LocalValidatorFactoryBean javadoc。spring-doc.cadn.net.cn

配置一个 DataBinder

您可以使用Validator配置DataBinder实例。配置完成后,可通过调用binder.validate()来触发Validator功能。 所有验证Errors将自动添加到绑定器的BindingResult中。spring-doc.cadn.net.cn

以下示例显示了如何将 DataBinder 用于编程方式,在绑定到目标对象后调用验证逻辑:spring-doc.cadn.net.cn

Foo target = new Foo();
DataBinder binder = new DataBinder(target);
binder.setValidator(new FooValidator());

// bind to the target object
binder.bind(propertyValues);

// validate the target object
binder.validate();

// get BindingResult that includes any validation errors
BindingResult results = binder.getBindingResult();
val target = Foo()
val binder = DataBinder(target)
binder.validator = FooValidator()

// bind to the target object
binder.bind(propertyValues)

// validate the target object
binder.validate()

// get BindingResult that includes any validation errors
val results = binder.bindingResult

您也可以通过DataBinderValidator配置多个dataBinder.addValidators实例。这在将全局配置的bean验证与Spring dataBinder.replaceValidators在DataBinder实例上本地配置相结合时非常有用。参见 Spring MVC验证配置spring-doc.cadn.net.cn

Spring MVC 3 验证

查看 验证 部分在Spring MVC章节中。spring-doc.cadn.net.cn