对于最新的稳定版本,请使用 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
-
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 的@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
-
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
包含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"
本身就是一个MessagreSourceResolvable
包含错误代码"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 一章中的 验证。