Validation

Spring WebFlux 内置用于 @RequestMapping 方法(包括 Java Bean Validation)的 Validation。可以在两个级别其中一个级别应用验证:

Spring WebFlux has built-in Validation for @RequestMapping methods, including Java Bean Validation. Validation may be applied at one of two levels:

  1. @ModelAttribute, @RequestBody, and @RequestPart argument resolvers validate a method argument individually if the method parameter is annotated with Jakarta @Valid or Spring’s @Validated, AND there is no Errors or BindingResult parameter immediately after, AND method validation is not needed (to be discussed next). The exception raised in this case is MethodArgumentNotValidException.

  2. When @Constraint annotations such as @Min, @NotBlank and others are declared directly on method parameters, or on the method (for the return value), then method validation must be applied, and that supersedes validation at the method argument level because method validation covers both method parameter constraints and nested constraints via @Valid. The exception raised in this case is HandlerMethodValidationException.

应用程序必须处理 MethodArgumentNotValidExceptionHandlerMethodValidationException,因为根据控制器方法的签名可能会引发其中任一个异常。但这两个异常的设计非常相似,并且可以用几乎相同的代码来处理。主要区别在于前者适用于单个对象,而后者适用于方法参数列表。

Applications must handle both MethodArgumentNotValidException and HandlerMethodValidationException as either may be raised depending on the controller method signature. The two exceptions, however are designed to be very similar, and can be handled with almost identical code. The main difference is that the former is for a single object while the latter is for a list of method parameters.

@Valid 不是约束注释,而是对象中嵌套约束的注释。因此,@Valid 本身不会导致方法验证。另一方面,@NotNull 是一个约束,将它添加到 @Valid 参数会导致方法验证。对于可空性,还可以使用 @RequestBody@ModelAttributerequired 标志。

@Valid is not a constraint annotation, but rather for nested constraints within an Object. Therefore, by itself @Valid does not lead to method validation. @NotNull on the other hand is a constraint, and adding it to an @Valid parameter leads to method validation. For nullability specifically, you may also use the required flag of @RequestBody or @ModelAttribute.

方法验证可以与`Errors`或`BindingResult`方法参数结合使用。但是,仅当所有验证错误紧跟在具有`Errors`的某个方法参数上时,才会调用控制器方法。如果其他任何方法参数上存在验证错误,则会抛出`HandlerMethodValidationException`。

Method validation may be used in combination with Errors or BindingResult method parameters. However, the controller method is called only if all validation errors are on method parameters with an Errors immediately after. If there are validation errors on any other method parameter then HandlerMethodValidationException is raised.

您可以通过 WebMvc config 在全局配置 Validator,或者通过 @Controller@ControllerAdvice 中的 @InitBinder 方法在本地配置 Validator。您还可以使用多个验证器。

You can configure a Validator globally through the WebMvc config, or locally through an @InitBinder method in an @Controller or @ControllerAdvice. You can also use multiple validators.

如果控制器具有类级别的 @Validated,则 method validation is applied 通过 AOP 代理。要利用 Spring 框架 6.1 中添加的 Spring MVC 内置方法验证支持,您需要从控制器中删除类级别的 @Validated 注释。

If a controller has a class level @Validated, then method validation is applied through an AOP proxy. In order to take advantage of the Spring MVC built-in support for method validation added in Spring Framework 6.1, you need to remove the class level @Validated annotation from the controller.

Error Responses部分提供了如何处理`MethodArgumentNotValidException`和`HandlerMethodValidationException`的更多详细信息,以及如何通过`MessageSource`和特定区域设置与语言的资源包自定义其渲染。

The Error Responses section provides further details on how MethodArgumentNotValidException and HandlerMethodValidationException are handled, and also how their rendering can be customized through a MessageSource and locale and language specific resource bundles.

为了进一步自定义处理方法验证错误,可以扩展`ResponseEntityExceptionHandler`或在控制器或`@ControllerAdvice`中使用`@ExceptionHandler`方法,并直接处理`HandlerMethodValidationException`。此异常包含`ParameterValidationResult`列表,这些列表按方法参数对验证错误进行分组。可以迭代这些列表,或通过控制器方法参数类型提供带有回调方法的访问者:

For further custom handling of method validation errors, you can extend ResponseEntityExceptionHandler or use an @ExceptionHandler method in a controller or in a @ControllerAdvice, and handle HandlerMethodValidationException directly. The exception contains a list of`ParameterValidationResult`s that group validation errors by method parameter. You can either iterate over those, or provide a visitor with callback methods by controller method parameter type:

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