Spring Framework 提供了对 Java Bean 验证 API 的支持。

Bean 验证概述

Bean Validation 通过约束声明和 Java 应用程序的元数据。要使用它,您可以使用 声明性验证约束,然后由运行时强制执行。有 内置约束,您还可以定义自己的自定义约束。

请考虑以下示例,该示例显示了一个具有两个属性的简单模型:PersonForm

  • Java

  • Kotlin

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

Bean Validation 允许您声明约束,如以下示例所示:

  • Java

  • Kotlin

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 验证器根据声明的 约束。请参阅 Bean Validation 以获取有关 API。请参阅 Hibernate Validator 文档 特定约束。了解如何将 Bean 验证提供程序设置为 Spring 豆子,继续阅读。

配置 Bean 验证提供程序

Spring 提供了对 Bean 验证 API 的完全支持,包括 Bean Validation 提供程序作为 Spring Bean。这允许您注入 or where 验证 是您的应用程序中需要的。jakarta.validation.ValidatorFactoryjakarta.validation.Validator

您可以使用 将默认验证器配置为 Spring bean,如以下示例所示:LocalValidatorFactoryBean

  • Java

  • XML

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 验证者,应存在于类路径中,并被自动检测。

注入雅加达验证器

LocalValidatorFactoryBean实现 和 ,因此您可以将对后者的引用注入到 如果您希望直接使用 Bean 验证 API,请应用验证逻辑, 如以下示例所示:jakarta.validation.ValidatorFactoryjakarta.validation.Validator

  • Java

  • Kotlin

import jakarta.validation.Validator;

@Service
public class MyService {

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

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

注入 Spring 验证器

除了实现 之外,还适配 ,所以可以注入一个引用 如果您的 Bean 需要 Spring Validation API,则为后者。jakarta.validation.ValidatorLocalValidatorFactoryBeanorg.springframework.validation.Validator

例如:

  • Java

  • Kotlin

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)

当用作 时,调用基础 ,然后将 s 调整为 s,并将它们注册到对象中 传入方法。org.springframework.validation.ValidatorLocalValidatorFactoryBeanjakarta.validation.ValidatorContraintViolationFieldErrorErrorsvalidate

配置自定义约束

每个 Bean 验证约束由两部分组成:

  • 声明约束及其可配置属性的批注。@Constraint

  • 实现的接口的实现 约束的行为。jakarta.validation.ConstraintValidator

若要将声明与实现相关联,每个批注 引用相应的实现类。在运行时,当 在域模型中会遇到约束注释。@ConstraintConstraintValidatorConstraintValidatorFactory

默认情况下,配置一个使用 Spring 创建实例的实例。这让您的自定义对象像任何其他 Spring Bean 一样从依赖注入中受益。LocalValidatorFactoryBeanSpringConstraintValidatorFactoryConstraintValidatorConstraintValidators

下面的示例显示了一个自定义声明,后跟一个使用 Spring 进行依赖项注入的关联实现:@ConstraintConstraintValidator

  • Java

  • Kotlin

@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
  • Java

  • Kotlin

import jakarta.validation.ConstraintValidator;

public class MyConstraintValidator implements ConstraintValidator {

	@Autowired;
	private Foo aDependency;

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

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

	// ...
}

如前面的示例所示,实现可以像任何其他 Spring Bean 一样具有依赖关系。ConstraintValidator@Autowired

弹簧驱动方法验证

您可以将 Bean Validation 的方法验证功能集成到 通过 Bean 定义的 Spring 上下文:MethodValidationPostProcessor

  • Java

  • XML

import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

@Configuration
public class AppConfig {

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

要获得 Spring 驱动方法验证的资格,需要对目标类进行注释 带有 Spring 的注解,也可以选择性地声明验证 要使用的组。请参阅 MethodValidationPostProcessor,了解 Hibernate Validator 和 Bean Validation 提供程序的设置详细信息。@Validated

方法验证依赖于围绕 目标类,接口上方法的 JDK 动态代理或 CGLIB 代理。 使用代理存在某些限制,了解 AOP 代理中介绍了其中一些限制。另外,请记住 始终在代理类上使用方法和访问器;直接字段访问将不起作用。

Spring MVC 和 WebFlux 内置了对相同底层方法验证的支持,但没有 对 AOP 的需求。因此,请检查本节的其余部分,并参阅 Spring MVC 验证错误响应部分,以及 WebFlux 验证错误响应部分。

方法验证异常

默认情况下,使用 返回的 s 集引发。作为替代方案, 你可以用 S 来代替 适应错误。要启用,请设置以下标志:jakarta.validation.ConstraintViolationExceptionConstraintViolationjakarta.validation.ValidatorMethodValidationExceptionConstraintViolationMessageSourceResolvable

  • Java

  • XML

import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;

@Configuration
public class AppConfig {

	@Bean
	public static MethodValidationPostProcessor validationPostProcessor() {
		MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
		processor.setAdaptConstraintViolations(true);
		return processor;
	}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
	<property name="adaptConstraintViolations" value="true"/>
</bean>

MethodValidationException包含 S 的列表,其中 按方法参数对错误进行分组,每个错误都公开一个 、 参数 值,以及改编自 s 的错误列表。对于具有级联冲突的方法参数 字段和属性,是 将验证错误实现并公开为 s。ParameterValidationResultMethodParameterMessageSourceResolvableConstraintViolation@ValidParameterValidationResultParameterErrorsorg.springframework.validation.ErrorsFieldError

自定义验证错误

改编后的错误可以转化为错误消息 通过配置的区域设置和特定语言向用户显示 资源包。本节提供示例进行说明。MessageSourceResolvableMessageSource

给定以下类声明:

  • Java

  • Kotlin

record Person(@Size(min = 1, max = 10) String name) {
}

@Validated
public class MyService {

	void addStudent(@Valid Person person, @Max(2) int degrees) {
		// ...
	}
}
@JvmRecord
internal data class Person(@Size(min = 1, max = 10) val name: String)

@Validated
class MyService {

	fun addStudent(person: @Valid Person?, degrees: @Max(2) Int) {
		// ...
	}
}

A on 适用于具有以下条件的 a:ConstraintViolationPerson.name()FieldError

  • 错误代码 、 、 和"Size.student.name""Size.name""Size.java.lang.String""Size"

  • 消息参数 、 和 (字段名称和约束属性)"name"101

  • 默认消息“大小必须介于 1 和 10 之间”

若要自定义默认消息,可以使用上述任何错误代码和消息参数向 MessageSource 资源包添加属性。另请注意, message 参数本身是一个带有错误代码的参数,也可以自定义。例如:"name"MessagreSourceResolvable"student.name""name"

性能
Size.student.name=Please, provide a {0} that is between {2} and {1} characters long
student.name=username

方法参数上的 A 与 a 的适配如下:ConstraintViolationdegreesMessageSourceResolvable

  • 错误代码 , , ,"Max.myService#addStudent.degrees""Max.degrees""Max.int""Max"

  • 消息参数 “degrees2 和 2(字段名称和 constraint 属性)

  • 默认消息“必须小于或等于 2”

若要自定义上述默认消息,可以添加如下属性:

性能
Max.degrees=You cannot provide more than {1} {0}

其他配置选项

默认配置对大多数人来说就足够了 例。有许多配置选项可用于各种 Bean 验证 构造,从消息插值到遍历解析。有关这些选项的更多信息,请参阅 LocalValidatorFactoryBean javadoc。LocalValidatorFactoryBean

配置DataBinder

您可以使用 .配置完成后,您可以 调用 by 调用 .任何验证都是 自动添加到活页夹的 .DataBinderValidatorValidatorbinder.validate()ErrorsBindingResult

下面的示例演示如何以编程方式使用 绑定到目标对象后的逻辑:DataBinder

  • Java

  • Kotlin

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

您还可以通过 和 配置具有多个实例的 a。这在以下情况下很有用 将全局配置的 Bean 验证与配置的 Spring 相结合 在 DataBinder 实例上本地。请参阅 Spring MVC 验证配置DataBinderValidatordataBinder.addValidatorsdataBinder.replaceValidatorsValidator

Spring MVC 3 验证

请参阅 Spring MVC 一章中的验证