13 changed files with 409 additions and 69 deletions
@ -0,0 +1,111 @@
@@ -0,0 +1,111 @@
|
||||
[[mvc-ann-validation]] |
||||
= Validation |
||||
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-validation.adoc[See equivalent in the Servlet stack]# |
||||
|
||||
Spring WebFlux has built-in xref:core/validation/validator.adoc[Validation] support for |
||||
`@RequestMapping` methods, including the option to use |
||||
xref:core/validation/beanvalidation.adoc[Java Bean Validation]. |
||||
The validation support works on two levels. |
||||
|
||||
First, method parameters such as |
||||
xref:web/webflux/controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute], |
||||
xref:web/webflux/controller/ann-methods/requestbody.adoc[@RequestBody], and |
||||
xref:web/webflux/controller/ann-methods/multipart-forms.adoc[@RequestPart] do perform |
||||
validation if annotated with Jakarta's `@Valid` or Spring's `@Validated` annotation, and |
||||
raise `MethodArgumentNotValidException` in case of validation errors. If you want to handle |
||||
the errors in the controller method instead, you can declare an `Errors` or `BindingResult` |
||||
method parameter immediately after the validated parameter. |
||||
|
||||
Second, if https://beanvalidation.org/[Java Bean Validation] is present _AND_ other method |
||||
parameters, e.g. `@RequestHeader`, `@RequestParam`, `@PathVariable` have `@Constraint` |
||||
annotations, then method validation is applied to all method arguments, raising |
||||
`HandlerMethodValidationException` in case of validation errors. You can still declare an |
||||
`Errors` or `BindingResult` after an `@Valid` method parameter, and handle validation |
||||
errors within the controller method, as long as there are no validation errors on other |
||||
method arguments. |
||||
|
||||
You can configure a `Validator` globally through the |
||||
xref:web/webflux/config.adoc#webflux-config-validation[WebMvc config], or locally |
||||
through an xref:web/webflux/controller/ann-initbinder.adoc[@InitBinder] method in an |
||||
`@Controller` or `@ControllerAdvice`. You can also use multiple validators. |
||||
|
||||
NOTE: If a controller has a class level `@Validated`, then |
||||
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method[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. |
||||
|
||||
The xref:web/webmvc/mvc-ann-rest-exceptions.adoc[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. |
||||
|
||||
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: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
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) { |
||||
// ... |
||||
} |
||||
}); |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
// 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) { |
||||
// ... |
||||
} |
||||
}) |
||||
---- |
||||
====== |
||||
@ -0,0 +1,112 @@
@@ -0,0 +1,112 @@
|
||||
[[mvc-ann-validation]] |
||||
= Validation |
||||
|
||||
[.small]#xref:web/webflux/controller/ann-validation.adoc[See equivalent in the Reactive stack]# |
||||
|
||||
Spring MVC has built-in xref:core/validation/validator.adoc[Validation] support for |
||||
`@RequestMapping` methods, including the option to use |
||||
xref:core/validation/beanvalidation.adoc[Java Bean Validation]. |
||||
The validation support works on two levels. |
||||
|
||||
First, method parameters such as |
||||
xref:web/webmvc/mvc-controller/ann-methods/modelattrib-method-args.adoc[@ModelAttribute], |
||||
xref:web/webmvc/mvc-controller/ann-methods/requestbody.adoc[@RequestBody], and |
||||
xref:web/webmvc/mvc-controller/ann-methods/multipart-forms.adoc[@RequestPart] do perform |
||||
validation if annotated with Jakarta's `@Valid` or Spring's `@Validated` annotation, and |
||||
raise `MethodArgumentNotValidException` in case of validation errors. If you want to handle |
||||
the errors in the controller method instead, you can declare an `Errors` or `BindingResult` |
||||
method parameter immediately after the validated parameter. |
||||
|
||||
Second, if https://beanvalidation.org/[Java Bean Validation] is present _AND_ other method |
||||
parameters, e.g. `@RequestHeader`, `@RequestParam`, `@PathVariable` have `@Constraint` |
||||
annotations, then method validation is applied to all method arguments, raising |
||||
`HandlerMethodValidationException` in case of validation errors. You can still declare an |
||||
`Errors` or `BindingResult` after an `@Valid` method parameter, and handle validation |
||||
errors within the controller method, as long as there are no validation errors on other |
||||
method arguments. Method validation is also applied to the return value if the method |
||||
is annotated with `@Valid` or has other `@Constraint` annotations. |
||||
|
||||
You can configure a `Validator` globally through the |
||||
xref:web/webmvc/mvc-config/validation.adoc[WebMvc config], or locally through an |
||||
xref:web/webmvc/mvc-controller/ann-initbinder.adoc[@InitBinder] method in an |
||||
`@Controller` or `@ControllerAdvice`. You can also use multiple validators. |
||||
|
||||
NOTE: If a controller has a class level `@Validated`, then |
||||
xref:core/validation/beanvalidation.adoc#validation-beanvalidation-spring-method[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. |
||||
|
||||
The xref:web/webmvc/mvc-ann-rest-exceptions.adoc[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. |
||||
|
||||
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: |
||||
|
||||
[tabs] |
||||
====== |
||||
Java:: |
||||
+ |
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
||||
---- |
||||
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) { |
||||
// ... |
||||
} |
||||
}); |
||||
---- |
||||
|
||||
Kotlin:: |
||||
+ |
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
||||
---- |
||||
// 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) { |
||||
// ... |
||||
} |
||||
}) |
||||
---- |
||||
====== |
||||
Loading…
Reference in new issue