验证
Spring MVC 为 @RequestMapping 方法提供了内置的验证功能,包括Java Bean 验证。
验证可以应用于以下两个级别之一:
-
Java Bean Validation 个别应用于 @ModelAttribute、 @RequestBody 和 @RequestPart 方法参数上, 只要它们使用了
@jakarta.validation.Valid或 Spring 的@Validated注解,并且是一个命令对象而非如Map或Collection这样的容器, 在方法签名中没有紧随其后的Errors或BindingResult,并且不需要方法验证(见下文)。验证方法参数时单独抛出的异常为MethodArgumentNotValidException。 -
Java Bean Validation 会在方法上应用,当如
@Constraint这样的注解直接声明在方法参数上,或对返回值的方法上,并且它优先于任何可能单独应用于方法参数的验证,因为方法验证涵盖了通过@Valid的方法参数约束和嵌套约束。HandlerMethodValidationException是在方法上应用验证时抛出的异常。
应用程序应处理 both MethodArgumentNotValidException 和
HandlerMethodValidationException,因为根据控制器方法签名,两者都可能被抛出。然而,这两个异常设计得非常相似,可以用几乎相同的代码来处理。主要的区别在于前者针对单个
对象,而后者针对方法参数的列表。
@Valid 不是约束注解,而是用于对象内的嵌套约束。
因此,仅凭 @Valid 本身不会触发方法验证。@NotNull
则是一个约束注解,将其添加到 @Valid 参数上会引发方法验证。
对于空值性检查,你也可以使用 @RequestBody 或 @ModelAttribute 的 required 标志。 |
方法验证可与 Errors 或 BindingResult 方法参数结合使用。但是,仅当所有验证错误都出现在带有 Errors 的方法参数上时,才会立即调用控制器方法。如果其他任何方法参数上存在验证错误,则会引发 HandlerMethodValidationException。
您可以通过
WebMvc 配置全局配置一个 Validator,或通过
@Controller 或 @ControllerAdvice 中的
@InitBinder 方法进行局部配置。您还可以使用多个验证器。
如果一个控制器在类级别上具有 @Validated 注解,则
方法验证将通过 AOP 代理应用。
为了利用 Spring Framework 6.1 中添加的 Spring MVC 对方法验证的内置支持,您需要从控制器中移除类级别的
@Validated 注解。 |
错误响应 部分提供了有关如何处理 MethodArgumentNotValidException 和 HandlerMethodValidationException 的更多详细信息,以及如何通过 MessageSource 和特定于区域设置及语言的资源包来自定义其呈现方式。
如需进一步自定义处理方法验证错误,您可以在控制器或 @ControllerAdvice 中扩展
ResponseEntityExceptionHandler 或使用一个 @ExceptionHandler 方法,并直接处理 HandlerMethodValidationException。
该异常包含一个按方法参数分组的验证错误 ParameterValidationResult 列表。您可以遍历这些列表,或为控制器方法参数类型提供带有回调方法的访问者:
-
Java
-
Kotlin
HandlerMethodValidationException ex = ... ;
ex.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
// ...
}
@Override
public void requestParam(@Nullable RequestParam requestParam, ParameterValidationResult result) {
// ...
}
@Override
public void modelAttribute(@Nullable ModelAttribute modelAttribute, ParameterErrors errors) {
// ...
@Override
public void other(ParameterValidationResult result) {
// ...
}
});
// HandlerMethodValidationException
val ex
ex.visitResults(object : HandlerMethodValidationException.Visitor {
override fun requestHeader(requestHeader: RequestHeader, result: ParameterValidationResult) {
// ...
}
override fun requestParam(requestParam: RequestParam?, result: ParameterValidationResult) {
// ...
}
override fun modelAttribute(modelAttribute: ModelAttribute?, errors: ParameterErrors) {
// ...
}
// ...
override fun other(result: ParameterValidationResult) {
// ...
}
})