验证
Spring WebFlux内置了对@RequestMapping
方法的验证,包括Java Bean验证。验证可以应用于两个级别之一
-
@ModelAttribute、@RequestBody和@RequestPart参数解析器会单独验证方法参数,如果方法参数用Jakarta
@Valid
或Spring的@Validated
注解,并且紧随其后没有Errors
或BindingResult
参数,并且不需要方法验证(将在后面讨论)。在这种情况下引发的异常是WebExchangeBindException
。 -
当
@Constraint
注解(例如@Min
、@NotBlank
等)直接声明在方法参数上或方法上(对于返回值)时,必须应用方法验证,并且这会取代方法参数级别的验证,因为方法验证涵盖了方法参数约束和通过@Valid
的嵌套约束。在这种情况下引发的异常是HandlerMethodValidationException
。
应用程序必须同时处理WebExchangeBindException
和HandlerMethodValidationException
,因为根据控制器方法签名,任何一个都可能被引发。但是,这两个异常的设计非常相似,可以用几乎相同的代码处理。主要区别在于前者是针对单个对象,而后者是针对方法参数列表。
@Valid 不是约束注解,而是用于对象内的嵌套约束。因此,@Valid 本身不会导致方法验证。另一方面,@NotNull 是一个约束,将其添加到@Valid 参数会导致方法验证。对于可空性,您也可以使用@RequestBody 或@ModelAttribute 的required 标志。 |
方法验证可以与Errors
或BindingResult
方法参数结合使用。但是,只有当所有验证错误都出现在带有紧随其后的Errors
的方法参数上时,才会调用控制器方法。如果任何其他方法参数上存在验证错误,则会引发HandlerMethodValidationException
。
您可以通过WebFlux配置全局配置Validator
,或通过@Controller
或@ControllerAdvice
中的@InitBinder方法局部配置。您还可以使用多个验证器。
如果控制器具有类级别的@Validated ,则通过AOP代理应用方法验证。为了利用Spring Framework 6.1中添加的Spring MVC对方法验证的内置支持,您需要从控制器中删除类级别的@Validated 注解。 |
错误响应部分提供了关于如何处理WebExchangeBindException
和HandlerMethodValidationException
以及如何通过MessageSource
和特定于语言环境和语言的资源包自定义其呈现的更多详细信息。
对于方法验证错误的进一步自定义处理,您可以扩展ResponseEntityExceptionHandler
或在控制器或@ControllerAdvice
中使用@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) {
// ...
}
})