验证 (Validation)
默认情况下,如果类路径上存在 Bean Validation 实现(例如 Hibernate Validator),Spring 会注册 LocalValidatorFactoryBean 作为全局验证器(Validator),用于在控制器方法参数上配合 @Valid 和 @Validated 使用。
自定义全局验证器
你可以自定义全局 Validator 实例:
java
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public Validator getValidator() {
Validator validator = new OptionalValidatorFactoryBean();
// 进行自定义配置...
return validator;
}
}kotlin
@Configuration
class WebConfiguration : WebMvcConfigurer {
override fun getValidator(): Validator {
val validator = OptionalValidatorFactoryBean()
// ...
return validator
}
}xml
<mvc:annotation-driven validator="globalValidator"/>局部验证器注册
除了全局验证器,你也可以在特定的控制器中注册 Validator 实现,这通常通过 @InitBinder 完成:
java
@Controller
public class MyController {
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.addValidators(new FooValidator());
}
}kotlin
@Controller
class MyController {
@InitBinder
fun initBinder(binder: WebDataBinder) {
binder.addValidators(FooValidator())
}
}提示
如果你需要在其他地方注入 LocalValidatorFactoryBean,请创建一个 Bean 并用 @Primary 标记它,以避免与 MVC 配置中声明的 Bean 冲突。
补充教学
1. @Valid vs @Validated
- @Valid: 源自标准的 JSR-303/JSR-380 (Bean Validation)。它可以用在方法参数、成员变量上。它不支持验证分组(Groups)。
- @Validated: 由 Spring 提供。它是
@Valid的增强版,最主要的区别在于它支持验证分组。此外,它还可以放在类级别(结合@Service等)来开启方法级别的参数验证。
2. 级联验证
如果要验证对象内部的列表或嵌套对象,必须在嵌套字段上添加 @Valid 注解,否则 Spring 只会验证顶层属性而忽略其内部成员。
3. 如何处理错误?
验证失败时,如果参数后面紧跟一个 BindingResult 参数,Spring 会将错误信息填充到其中供你手动处理。如果没有 BindingResult,Spring 会抛出 MethodArgumentNotValidException(对于 @RequestBody)或 BindException(对于表单提交),通常由全局异常处理器统一拦截。