parent
a03a14797f
commit
df2617d575
|
@ -267,6 +267,7 @@
|
|||
***** xref:web/webmvc/mvc-controller/ann-methods/jackson.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-modelattrib-methods.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-initbinder.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-validation.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-exceptionhandler.adoc[]
|
||||
**** xref:web/webmvc/mvc-controller/ann-advice.adoc[]
|
||||
*** xref:web/webmvc-functional.adoc[]
|
||||
|
@ -361,6 +362,7 @@
|
|||
***** xref:web/webflux/controller/ann-methods/jackson.adoc[]
|
||||
**** xref:web/webflux/controller/ann-modelattrib-methods.adoc[]
|
||||
**** xref:web/webflux/controller/ann-initbinder.adoc[]
|
||||
**** xref:web/webflux/controller/ann-validation.adoc[]
|
||||
**** xref:web/webflux/controller/ann-exceptions.adoc[]
|
||||
**** xref:web/webflux/controller/ann-advice.adoc[]
|
||||
*** xref:web/webflux-functional.adoc[]
|
||||
|
|
|
@ -123,15 +123,12 @@ Validator, is expected to be present in the classpath and is automatically detec
|
|||
|
||||
|
||||
[[validation-beanvalidation-spring-inject]]
|
||||
=== Injecting a Validator
|
||||
=== Inject Jakarta Validator
|
||||
|
||||
`LocalValidatorFactoryBean` implements both `jakarta.validation.ValidatorFactory` and
|
||||
`jakarta.validation.Validator`, as well as Spring's `org.springframework.validation.Validator`.
|
||||
You can inject a reference to either of these interfaces into beans that need to invoke
|
||||
validation logic.
|
||||
|
||||
You can inject a reference to `jakarta.validation.Validator` if you prefer to work with the Bean
|
||||
Validation API directly, as the following example shows:
|
||||
`jakarta.validation.Validator`, so you can inject a reference to the latter to
|
||||
apply validation logic if you prefer to work with the Bean Validation API directly,
|
||||
as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
@ -160,8 +157,15 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
You can inject a reference to `org.springframework.validation.Validator` if your bean
|
||||
requires the Spring Validation API, as the following example shows:
|
||||
|
||||
[[validation-beanvalidation-spring-inject-adapter]]
|
||||
=== Inject Spring Validator
|
||||
|
||||
In addition to implementing `jakarta.validation.Validator`, `LocalValidatorFactoryBean`
|
||||
also adapts to `org.springframework.validation.Validator`, so you can inject a reference
|
||||
to the latter if your bean requires the Spring Validation API.
|
||||
|
||||
For example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
@ -190,9 +194,15 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
When used as `org.springframework.validation.Validator`, `LocalValidatorFactoryBean`
|
||||
invokes the underlying `jakarta.validation.Validator`, and then adapts
|
||||
``ContraintViolation``s to ``FieldError``s, and registers them with the `Errors` object
|
||||
passed into the `validate` method.
|
||||
|
||||
|
||||
|
||||
[[validation-beanvalidation-spring-constraints]]
|
||||
=== Configuring Custom Constraints
|
||||
=== Configure Custom Constraints
|
||||
|
||||
Each bean validation constraint consists of two parts:
|
||||
|
||||
|
@ -274,9 +284,8 @@ As the preceding example shows, a `ConstraintValidator` implementation can have
|
|||
[[validation-beanvalidation-spring-method]]
|
||||
=== Spring-driven Method Validation
|
||||
|
||||
You can integrate the method validation feature supported by Bean Validation 1.1 (and, as
|
||||
a custom extension, also by Hibernate Validator 4.3) into a Spring context through a
|
||||
`MethodValidationPostProcessor` bean definition:
|
||||
You can integrate the method validation feature of Bean Validation into a
|
||||
Spring context through a `MethodValidationPostProcessor` bean definition:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
|
@ -305,11 +314,11 @@ XML::
|
|||
----
|
||||
======
|
||||
|
||||
To be eligible for Spring-driven method validation, all target classes need to be annotated
|
||||
To be eligible for Spring-driven method validation, target classes need to be annotated
|
||||
with Spring's `@Validated` annotation, which can optionally also declare the validation
|
||||
groups to use. See
|
||||
{api-spring-framework}/validation/beanvalidation/MethodValidationPostProcessor.html[`MethodValidationPostProcessor`]
|
||||
for setup details with the Hibernate Validator and Bean Validation 1.1 providers.
|
||||
for setup details with the Hibernate Validator and Bean Validation providers.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
|
@ -320,6 +329,61 @@ xref:core/aop/proxying.adoc#aop-understanding-aop-proxies[Understanding AOP Prox
|
|||
to always use methods and accessors on proxied classes; direct field access will not work.
|
||||
====
|
||||
|
||||
By default, `jakarta.validation.ConstraintViolationException` is raised with the set of
|
||||
``ConstraintViolation``s returned by `jakarata.validation.Validator`. As an alternative,
|
||||
you can have `MethodValidationException` raised instead with ``ConstraintViolation``s
|
||||
adapted to `MessageSourceResolvable` errors. To enable set the following flag:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
|
||||
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public MethodValidationPostProcessor validationPostProcessor() {
|
||||
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
|
||||
processor.setAdaptConstraintViolations(true);
|
||||
return processor;
|
||||
}
|
||||
}
|
||||
|
||||
----
|
||||
|
||||
XML::
|
||||
+
|
||||
[source,xml,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor">
|
||||
<property name="adaptConstraintViolations" value="true"/>
|
||||
</bean>
|
||||
----
|
||||
======
|
||||
|
||||
`MethodValidationException` contains a list of ``ParameterValidationResult``s which
|
||||
group errors by method parameter, and each exposes a `MethodParameter`, the argument
|
||||
value, and a list of `MessageSourceResolvable` errors adapted from
|
||||
``ConstraintViolation``s. For `@Valid` method parameters with cascaded violations on
|
||||
fields and properties, the `ParameterValidationResult` is `ParameterErrors` which
|
||||
implements `org.springframework.validation.Errors` and exposes validation errors as
|
||||
``FieldError``s.
|
||||
|
||||
The adapted `MessageSourceResolvable` errors can be turned into error messages to
|
||||
display to users through the configured
|
||||
xref:core/beans/context-introduction.adoc#context-functionality-messagesource[`MessageSource`]
|
||||
based on locale and language specific resource bundles.
|
||||
|
||||
NOTE: Spring MVC and WebFlux have built-in support for method validation, and therefore
|
||||
for web controller methods there is no need for a class level `@Validated` and an AOP proxy.
|
||||
See the Spring MVC xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation] section,
|
||||
the WebFlux xref:web/webflux/controller/ann-validation.adoc[Validation] section,
|
||||
and the xref:web/webmvc/mvc-controller/ann-validation.adoc[Error Responses] section.
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -67,23 +67,23 @@ from an existing `ProblemDetail`. This could be done centrally, e.g. from an
|
|||
|
||||
|
||||
[[webflux-ann-rest-exceptions-i18n]]
|
||||
== Internationalization
|
||||
== Customization and i18n
|
||||
[.small]#xref:web/webmvc/mvc-ann-rest-exceptions.adoc#mvc-ann-rest-exceptions-i18n[See equivalent in the Servlet stack]#
|
||||
|
||||
It is a common requirement to internationalize error response details, and good practice
|
||||
to customize the problem details for Spring WebFlux exceptions. This section describes the
|
||||
support for that.
|
||||
It is a common requirement to customize and internationalize error response details.
|
||||
It is also good practice to customize the problem details for Spring WebFlux exceptions
|
||||
to avoid revealing implementation details. This section describes the support for that.
|
||||
|
||||
`ErrorResponse` exposes message codes for "type", "title", and "detail", in addition to
|
||||
An `ErrorResponse` exposes message codes for "type", "title", and "detail", as well as
|
||||
message code arguments for the "detail" field. `ResponseEntityExceptionHandler` resolves
|
||||
these through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
|
||||
and updates the `ProblemDetail` accordingly.
|
||||
and updates the corresponding `ProblemDetail` fields accordingly.
|
||||
|
||||
The default strategy for message codes follows the pattern:
|
||||
|
||||
`problemDetail.[type|title|detail].[fully qualified exception class name]`
|
||||
|
||||
Some `ErrorResponse` may expose more than one message code, typically adding a suffix
|
||||
An `ErrorResponse` may expose more than one message code, typically adding a suffix
|
||||
to the default message code. The table below lists message codes, and arguments for
|
||||
Spring WebFlux exceptions:
|
||||
|
||||
|
@ -92,28 +92,19 @@ Spring WebFlux exceptions:
|
|||
|===
|
||||
| Exception | Message Code | Message Code Arguments
|
||||
|
||||
| `UnsupportedMediaTypeStatusException`
|
||||
| `HandlerMethodValidationException`
|
||||
| (default)
|
||||
| `+{0}+` the media type that is not supported, `+{1}+` list of supported media types
|
||||
| `+{0}+` list all validation errors.
|
||||
Message codes and arguments for each error are also resolved via `MessageSource`.
|
||||
|
||||
| `UnsupportedMediaTypeStatusException`
|
||||
| (default) + ".parseError"
|
||||
|
|
||||
| `MethodNotAllowedException`
|
||||
| (default)
|
||||
| `+{0}+` the current HTTP method, `+{1}+` the list of supported HTTP methods
|
||||
|
||||
| `MissingRequestValueException`
|
||||
| (default)
|
||||
| `+{0}+` a label for the value (e.g. "request header", "cookie value", ...), `+{1}+` the value name
|
||||
|
||||
| `UnsatisfiedRequestParameterException`
|
||||
| (default)
|
||||
| `+{0}+` the list of parameter conditions
|
||||
|
||||
| `WebExchangeBindException`
|
||||
| (default)
|
||||
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
|
||||
Message codes and arguments for each error within the `BindingResult` are also resolved
|
||||
via `MessageSource`.
|
||||
|
||||
| `NotAcceptableStatusException`
|
||||
| (default)
|
||||
| `+{0}+` list of supported media types
|
||||
|
@ -126,9 +117,22 @@ via `MessageSource`.
|
|||
| (default)
|
||||
| `+{0}+` the failure reason provided to the class constructor
|
||||
|
||||
| `MethodNotAllowedException`
|
||||
| `UnsupportedMediaTypeStatusException`
|
||||
| (default)
|
||||
| `+{0}+` the current HTTP method, `+{1}+` the list of supported HTTP methods
|
||||
| `+{0}+` the media type that is not supported, `+{1}+` list of supported media types
|
||||
|
||||
| `UnsupportedMediaTypeStatusException`
|
||||
| (default) + ".parseError"
|
||||
|
|
||||
|
||||
| `UnsatisfiedRequestParameterException`
|
||||
| (default)
|
||||
| `+{0}+` the list of parameter conditions
|
||||
|
||||
| `WebExchangeBindException`
|
||||
| (default)
|
||||
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
|
||||
Message codes and arguments for each error are also resolved via `MessageSource`.
|
||||
|
||||
|===
|
||||
|
||||
|
|
|
@ -160,10 +160,13 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
Note that use of `@ModelAttribute` is optional -- for example, to set its attributes.
|
||||
By default, any argument that is not a simple value type (as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty])
|
||||
and is not resolved by any other argument resolver is treated as if it were annotated
|
||||
with `@ModelAttribute`.
|
||||
If method validation applies because other parameters have `@Constraint` annotations,
|
||||
then `HandlerMethodValidationException` would be raised instead. See the section on
|
||||
controller method xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
|
||||
|
||||
TIP: Using `@ModelAttribute` is optional. By default, any argument that is not a simple
|
||||
value type as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
|
||||
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
|
||||
|
||||
|
||||
|
|
|
@ -176,6 +176,10 @@ Kotlin::
|
|||
======
|
||||
--
|
||||
|
||||
If method validation applies because other parameters have `@Constraint` annotations,
|
||||
then `HandlerMethodValidationException` is raised instead. See the section on
|
||||
xref:web/webflux/controller/ann-validation.adoc[Validation].
|
||||
|
||||
To access all multipart data as a `MultiValueMap`, you can use `@RequestBody`,
|
||||
as the following example shows:
|
||||
|
||||
|
@ -306,5 +310,3 @@ file upload.
|
|||
|
||||
Received part events can also be relayed to another service by using the `WebClient`.
|
||||
See xref:web/webflux-webclient/client-body.adoc#webflux-client-body-multipart[Multipart Data].
|
||||
|
||||
|
||||
|
|
|
@ -89,4 +89,33 @@ Kotlin::
|
|||
----
|
||||
======
|
||||
|
||||
You can also declare an `Errors` parameter for access to validation errors, but in
|
||||
that case the request body must not be a `Mono`, and will be resolved first:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@PostMapping("/accounts")
|
||||
public void handle(@Valid @RequestBody Account account, Errors errors) {
|
||||
// use one of the onError* operators...
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@PostMapping("/accounts")
|
||||
fun handle(@Valid @RequestBody account: Mono<Account>) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
If method validation applies because other parameters have `@Constraint` annotations,
|
||||
then `HandlerMethodValidationException` is raised instead. For more details, see the
|
||||
section on xref:web/webflux/controller/ann-validation.adoc[Validation].
|
||||
|
||||
|
|
|
@ -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) {
|
||||
// ...
|
||||
}
|
||||
})
|
||||
----
|
||||
======
|
|
@ -67,23 +67,23 @@ from an existing `ProblemDetail`. This could be done centrally, e.g. from an
|
|||
|
||||
|
||||
[[mvc-ann-rest-exceptions-i18n]]
|
||||
== Internationalization
|
||||
== Customization and i18n
|
||||
[.small]#xref:web/webflux/ann-rest-exceptions.adoc#webflux-ann-rest-exceptions-i18n[See equivalent in the Reactive stack]#
|
||||
|
||||
It is a common requirement to internationalize error response details, and good practice
|
||||
to customize the problem details for Spring WebFlux exceptions. This section describes the
|
||||
support for that.
|
||||
It is a common requirement to customize and internationalize error response details.
|
||||
It is also good practice to customize the problem details for Spring MVC exceptions
|
||||
to avoid revealing implementation details. This section describes the support for that.
|
||||
|
||||
`ErrorResponse` exposes message codes for "type", "title", and "detail", in addition to
|
||||
An `ErrorResponse` exposes message codes for "type", "title", and "detail", as well as
|
||||
message code arguments for the "detail" field. `ResponseEntityExceptionHandler` resolves
|
||||
these through a xref:core/beans/context-introduction.adoc#context-functionality-messagesource[MessageSource]
|
||||
and updates the `ProblemDetail` accordingly.
|
||||
and updates the corresponding `ProblemDetail` fields accordingly.
|
||||
|
||||
The default strategy for message codes follows the pattern:
|
||||
|
||||
`problemDetail.[type|title|detail].[fully qualified exception class name]`
|
||||
|
||||
Some `ErrorResponse` may expose more than one message code, typically adding a suffix
|
||||
An `ErrorResponse` may expose more than one message code, typically adding a suffix
|
||||
to the default message code. The table below lists message codes, and arguments for
|
||||
Spring MVC exceptions:
|
||||
|
||||
|
@ -100,6 +100,11 @@ Spring MVC exceptions:
|
|||
| (default)
|
||||
| `+{0}+` property name, `+{1}+` property value
|
||||
|
||||
| `HandlerMethodValidationException`
|
||||
| (default)
|
||||
| `+{0}+` list all validation errors.
|
||||
Message codes and arguments for each error are also resolved via `MessageSource`.
|
||||
|
||||
| `HttpMediaTypeNotAcceptableException`
|
||||
| (default)
|
||||
| `+{0}+` list of supported media types
|
||||
|
@ -131,8 +136,7 @@ Spring MVC exceptions:
|
|||
| `MethodArgumentNotValidException`
|
||||
| (default)
|
||||
| `+{0}+` the list of global errors, `+{1}+` the list of field errors.
|
||||
Message codes and arguments for each error within the `BindingResult` are also resolved
|
||||
via `MessageSource`.
|
||||
Message codes and arguments for each error are also resolvedvia `MessageSource`.
|
||||
|
||||
| `MissingRequestHeaderException`
|
||||
| (default)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
By default, if xref:core/validation/beanvalidation.adoc#validation-beanvalidation-overview[Bean Validation] is present
|
||||
on the classpath (for example, Hibernate Validator), the `LocalValidatorFactoryBean` is
|
||||
registered as a global xref:core/validation/validator.adoc[Validator] for use with `@Valid` and
|
||||
`Validated` on controller method arguments.
|
||||
`@Validated` on controller method arguments.
|
||||
|
||||
In Java configuration, you can customize the global `Validator` instance, as the
|
||||
following example shows:
|
||||
|
|
|
@ -144,7 +144,7 @@ Java::
|
|||
}
|
||||
|
||||
@PostMapping("update")
|
||||
public String update(@Valid AccountForm form, BindingResult result,
|
||||
public String update(AccountForm form, BindingResult result,
|
||||
@ModelAttribute(binding=false) Account account) { // <1>
|
||||
// ...
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ Kotlin::
|
|||
}
|
||||
|
||||
@PostMapping("update")
|
||||
fun update(@Valid form: AccountForm, result: BindingResult,
|
||||
fun update(form: AccountForm, result: BindingResult,
|
||||
@ModelAttribute(binding = false) account: Account): String { // <1>
|
||||
// ...
|
||||
}
|
||||
|
@ -210,10 +210,15 @@ Kotlin::
|
|||
<1> Validate the `Pet` instance.
|
||||
======
|
||||
|
||||
Note that using `@ModelAttribute` is optional (for example, to set its attributes).
|
||||
By default, any argument that is not a simple value type (as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty])
|
||||
and is not resolved by any other argument resolver is treated as if it were annotated
|
||||
with `@ModelAttribute`.
|
||||
If an `@ModelAttribute` is declared without `BindingResult` parameter after it, then
|
||||
`MethodArgumentNotValueException` is raised. However, if method validation applies because
|
||||
other parameters have `@Constraint` annotations, then `HandlerMethodValidationException`
|
||||
is raised instead. For more details, see the section on
|
||||
xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
|
||||
|
||||
TIP: Using `@ModelAttribute` is optional. By default, any parameter that is not a simple
|
||||
value type as determined by
|
||||
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]
|
||||
_AND_ that is not resolved by any other argument resolver is treated as an `@ModelAttribute`.
|
||||
|
||||
|
||||
|
|
|
@ -188,8 +188,7 @@ Java::
|
|||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@PostMapping("/")
|
||||
public String handle(@Valid @RequestPart("meta-data") MetaData metadata,
|
||||
BindingResult result) {
|
||||
public String handle(@Valid @RequestPart("meta-data") MetaData metadata, Errors errors) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
@ -199,12 +198,14 @@ Kotlin::
|
|||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@PostMapping("/")
|
||||
fun handle(@Valid @RequestPart("meta-data") metadata: MetaData,
|
||||
result: BindingResult): String {
|
||||
fun handle(@Valid @RequestPart("meta-data") metadata: MetaData, errors: Errors): String {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
If method validation applies because other parameters have `@Constraint` annotations,
|
||||
then `HandlerMethodValidationException` is raised instead. For more details, see the
|
||||
section on xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ Java::
|
|||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@PostMapping("/accounts")
|
||||
public void handle(@Valid @RequestBody Account account, BindingResult result) {
|
||||
public void handle(@Valid @RequestBody Account account, Errors errors) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
@ -58,10 +58,13 @@ Kotlin::
|
|||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@PostMapping("/accounts")
|
||||
fun handle(@Valid @RequestBody account: Account, result: BindingResult) {
|
||||
fun handle(@Valid @RequestBody account: Account, errors: Errors) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
If method validation applies because other parameters have `@Constraint` annotations,
|
||||
then `HandlerMethodValidationException` is raised instead. For more details, see the
|
||||
section on xref:web/webmvc/mvc-controller/ann-validation.adoc[Validation].
|
||||
|
||||
|
|
|
@ -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