此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.0! |
Java Bean 验证
Spring Framework 提供了对 Java Bean 验证 API 的支持。
Bean 验证概述
Bean Validation 提供了一种通用的验证方法,通过 constraint declaration 和 元数据。要使用它,您可以使用 声明性验证约束,然后由运行时强制执行。有 built-in constraints,您还可以定义自己的自定义 constraints。
请考虑以下示例,它显示了一个简单的PersonForm
model 具有两个属性:
-
Java
-
Kotlin
public class PersonForm {
private String name;
private int age;
}
class PersonForm(
private val name: String,
private val age: Int
)
Bean 验证允许您声明约束,如下例所示:
-
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 验证器根据声明的 约束。有关 API 的 API 创建。请参阅 Hibernate Validator 文档 特定约束。了解如何将 Bean 验证提供程序设置为 Spring Bean,请继续阅读。
配置 Bean 验证提供程序
Spring 提供了对 Bean 验证 API 的全面支持,包括
Bean Validation 提供程序作为 Spring Bean。这样,您就可以在邮件中注入jakarta.validation.ValidatorFactory
或jakarta.validation.Validator
Where 验证
在您的应用程序中需要。
您可以使用LocalValidatorFactoryBean
将默认 Validator 配置为 Spring
bean,如下例所示:
-
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 Validation 提供程序,例如 Hibernate Validator 应存在于 Classpath 中,并被自动检测。
注入 Jakarta Validator
LocalValidatorFactoryBean
同时实现jakarta.validation.ValidatorFactory
和jakarta.validation.Validator
,因此你可以将对后者的引用注入到
apply 验证逻辑(如果您更喜欢直接使用 Bean 验证 API),
如下例所示:
-
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 验证器
除了实施jakarta.validation.Validator
,LocalValidatorFactoryBean
还适应org.springframework.validation.Validator
,以便您可以注入引用
如果 bean 需要 Spring Validation API,则将其更改为后者。
例如:
-
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)
当用作org.springframework.validation.Validator
,LocalValidatorFactoryBean
调用底层jakarta.validation.Validator
,然后适应ConstraintViolation
s 更改为FieldError
s,并将它们注册到Errors
对象
传递到validate
方法。
配置自定义约束
每个 bean 验证约束由两部分组成:
-
一个
@Constraint
注解,用于声明约束及其可配置属性。 -
的
jakarta.validation.ConstraintValidator
实现 约束的行为。
要将声明与实现关联,每个@Constraint
注解
引用相应的ConstraintValidator
implementation 类。在运行时,ConstraintValidatorFactory
实例化引用的实现,当
约束注释。
默认情况下,LocalValidatorFactoryBean
配置SpringConstraintValidatorFactory
使用 Spring 创建ConstraintValidator
实例。这样,您的自定义ConstraintValidators
像任何其他 Spring bean 一样从依赖注入中受益。
以下示例显示了自定义@Constraint
声明后跟关联的ConstraintValidator
使用 Spring 进行依赖注入的实现:
-
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 {
// ...
}
如前面的示例所示,ConstraintValidator
implementation 可以有其依赖项@Autowired
就像任何其他 Spring bean 一样。
Spring 驱动的方法验证
您可以将 Bean Validation 的方法验证功能集成到
Spring 上下文通过MethodValidationPostProcessor
bean 定义:
-
Java
-
Kotlin
-
Xml
@Configuration
public class ApplicationConfiguration {
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
@Configuration
class ApplicationConfiguration {
companion object {
@Bean
@JvmStatic
fun validationPostProcessor() = MethodValidationPostProcessor()
}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
要获得 Spring 驱动的方法验证的资格,需要对目标类进行注释
与 Spring 的@Validated
注解,也可以选择声明验证
要使用的组。看MethodValidationPostProcessor
,了解 Hibernate Validator 和 Bean Validation 提供程序的设置详细信息。
Spring MVC 和 WebFlux 内置了对相同底层方法验证的支持,但没有 对 AOP 的需求。因此,请检查本节的其余部分,并参阅 Spring MVC 验证和错误响应部分,以及 WebFlux 验证和错误响应部分。
方法验证异常
默认情况下,jakarta.validation.ConstraintViolationException
使用ConstraintViolation
s 返回者jakarta.validation.Validator
.作为替代方案,
您可以拥有MethodValidationException
raise 替换为ConstraintViolation
s
适应于MessageSourceResolvable
错误。要启用,请设置以下标志:
-
Java
-
Kotlin
-
Xml
@Configuration
public class ApplicationConfiguration {
@Bean
public static MethodValidationPostProcessor validationPostProcessor() {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
processor.setAdaptConstraintViolations(true);
return processor;
}
}
@Configuration
class ApplicationConfiguration {
companion object {
@Bean
@JvmStatic
fun validationPostProcessor() = MethodValidationPostProcessor().apply {
setAdaptConstraintViolations(true)
}
}
}
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
<property name="adaptConstraintViolations" value="true"/>
</bean>
MethodValidationException
包含ParameterValidationResult
s 哪个
按方法参数对错误进行分组,每个错误都会公开一个MethodParameter
,则参数
值和MessageSourceResolvable
错误改编自ConstraintViolation
s.为@Valid
级联冲突 on 的方法参数
fields 和 properties 中,使用ParameterValidationResult
是ParameterErrors
哪
实现org.springframework.validation.Errors
并将验证错误暴露为FieldError
s.
自定义验证错误
改编的MessageSourceResolvable
错误可以转换为错误消息,以
通过配置的MessageSource
具有特定于区域设置和语言的功能
资源包。本节提供了一个示例进行说明。
给定以下类声明:
-
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) {
// ...
}
}
一个ConstraintViolation
上Person.name()
适应于FieldError
替换为以下内容:
-
错误代码
"Size.person.name"
,"Size.name"
,"Size.java.lang.String"
和"Size"
-
消息参数
"name"
,10
和1
(字段名称和 constraint 属性) -
默认消息 “size must be between 1 and 10”
要自定义默认消息,您可以使用上述任何错误代码和消息参数将属性添加到 MessageSource 资源包中。另请注意,
message 参数"name"
本身就是一个MessageSourceResolvable
包含错误代码"person.name"
和"name"
并且也可以定制。例如:
- 性能
-
Size.person.name=Please, provide a {0} that is between {2} and {1} characters long person.name=username
一个ConstraintViolation
在degrees
method 参数适配MessageSourceResolvable
替换为以下内容:
-
错误代码
"Max.myService#addStudent.degrees"
,"Max.degrees"
,"Max.int"
,"Max"
-
消息参数 “degrees2 和 2 (字段名称和 constraint 属性)
-
默认消息 “must be less than or equal to 2”
要自定义上述默认消息,您可以添加如下属性:
- 性能
-
Max.degrees=You cannot provide more than {1} {0}
其他配置选项
默认的LocalValidatorFactoryBean
配置足以满足大多数
例。各种 Bean 验证有许多配置选项
构造,从消息插值到遍历解析。请参阅LocalValidatorFactoryBean
javadoc 了解有关这些选项的更多信息。
配置DataBinder
您可以配置DataBinder
实例具有Validator
.配置完成后,您可以
调用Validator
通过调用binder.validate()
.任何验证Errors
是
自动添加到 Binder 的BindingResult
.
以下示例演示如何使用DataBinder
以编程方式调用 validation
绑定到目标对象后的逻辑:
-
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
您还可以配置DataBinder
具有多个Validator
实例dataBinder.addValidators
和dataBinder.replaceValidators
.这在以下情况下很有用
将全局配置的 bean 验证与 Spring 相结合Validator
配置
本地的 DataBinder 实例。参见 Spring MVC 验证配置。
Spring MVC 3 验证
参见 Spring MVC 一章中的 验证。