对于最新的稳定版本,请使用 Spring Framework 7.0.6!spring-doc.cadn.net.cn

验证

Spring WebFlux 为 @RequestMapping 方法提供了内置的验证功能,包括Java Bean 验证。 验证可以在以下两个级别之一应用:spring-doc.cadn.net.cn

  1. @ModelAttribute@RequestBody 以及 @RequestPart 参数解析器会单独验证方法参数,前提是该方法参数使用了 Jakarta 的 @Valid 或 Spring 的 @Validated 进行注解,并且其后没有紧跟着 ErrorsBindingResult 参数,并且不需要进行方法验证(接下来将讨论这一点)。这种情况下抛出的异常是 WebExchangeBindExceptionspring-doc.cadn.net.cn

  2. 当诸如 @Constraint@Min 和其他注解直接声明在方法参数上,或声明在方法上(用于返回值)时,则必须应用方法验证,这会覆盖方法参数级别的验证,因为方法验证同时涵盖了方法参数约束以及通过 @Valid 实现的嵌套约束。在这种情况下抛出的异常是 HandlerMethodValidationExceptionspring-doc.cadn.net.cn

应用程序必须同时处理 WebExchangeBindExceptionHandlerMethodValidationException,因为根据控制器方法签名的不同,可能会抛出其中任意一个。这两种异常的设计非常相似,可以用几乎相同的代码进行处理。主要区别在于前者用于单个对象,而后者用于方法参数列表。spring-doc.cadn.net.cn

@Valid 不是约束注解,而是用于对象内的嵌套约束。 因此,仅凭 @Valid 本身不会触发方法验证。@NotNull 则是一个约束注解,将其添加到 @Valid 参数上会引发方法验证。 对于空值性检查,你也可以使用 @RequestBody@ModelAttributerequired 标志。

方法验证可与 ErrorsBindingResult 方法参数结合使用。但是,仅当所有验证错误都出现在带有 Errors 的方法参数上时,才会立即调用控制器方法。如果其他任何方法参数上存在验证错误,则会引发 HandlerMethodValidationExceptionspring-doc.cadn.net.cn

您可以通过 WebFlux 配置 全局配置一个 Validator,或在 @Controller@ControllerAdvice 中通过 @InitBinder 方法进行局部配置。您还可以使用多个验证器。spring-doc.cadn.net.cn

如果一个控制器在类级别上具有 @Validated 注解,则 方法验证将通过 AOP 代理应用。 为了利用 Spring Framework 6.1 中添加的 Spring MVC 对方法验证的内置支持,您需要从控制器中移除类级别的 @Validated 注解。

错误响应 部分提供了有关如何处理 WebExchangeBindExceptionHandlerMethodValidationException 的更多详细信息,以及如何通过 MessageSource 和特定于区域设置及语言的资源包来自定义其呈现方式。spring-doc.cadn.net.cn

如需进一步自定义处理方法验证错误,您可以在控制器或 @ControllerAdvice 中扩展 ResponseEntityExceptionHandler 或使用一个 @ExceptionHandler 方法,并直接处理 HandlerMethodValidationException。 该异常包含一个按方法参数分组的验证错误 ParameterValidationResult 列表。您可以遍历这些列表,或为控制器方法参数类型提供带有回调方法的访问者:spring-doc.cadn.net.cn

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) {
			// ...
       }
})