diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index c2c59e16db9..c868d0b659e 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -732,7 +732,7 @@ public class OwnerController { URI variables are automatically converted to the appropriate type or`TypeMismatchException` is raised. Simple types -- `int`, `long`, `Date`, are supported by default and you can register support for any other data type. -// TODO: see <> and <>. +See <> and <>. URI variables can be named explicitly -- e.g. `@PathVariable("customId")`, but you can leave that detail out if the names are the same and your code is compiled with debugging @@ -962,13 +962,15 @@ Java 8+: `java.time.ZoneId` |`@RequestParam` |For access to Servlet request parameters. Parameter values are converted to the declared -method argument type. -// TODO: See <>. +method argument type. See <>. |`@RequestHeader` |For access to request headers. Header values are converted to the declared method argument -type. -// TODO: See <>. +type. See <>. + +|`@CookieValue` +|For access to cookies. Cookies values are converted to the declared method argument +type. See <>. |`@RequestBody` |For access to the HTTP request body. Body content is converted to the declared method @@ -1087,6 +1089,200 @@ class name of the return type. |=== +[[webflux-ann-typeconversion]] +==== Type Conversion +[.small]#<># + +Some annotated controller method arguments that represent String-based request input -- e.g. +`@RequestParam`, `@RequestHeader`, `@PathVariable`, `@MatrixVariable`, and `@CookieValue`, +may require type conversion if the argument is declared as something other than `String`. + +For such cases type conversion is automatically applied based on the configured converters. +By default simple types such as `int`, `long`, `Date`, etc. are supported. Type conversion +can be customized through a `WebDataBinder`, see <>, or by registering +`Formatters` with the `FormattingConversionService`, see +<>. + + +[[webflux-ann-requestparam]] +==== @RequestParam +[.small]#<># + +Use the `@RequestParam` annotation to bind Servlet request parameters (i.e. query +parameters or form data) to a method argument in a controller. + +The following code snippet shows the usage: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + @RequestMapping("/pets") + public class EditPetForm { + + // ... + + @GetMapping + public String setupForm(**@RequestParam("petId") int petId**, Model model) { + Pet pet = this.clinic.loadPet(petId); + model.addAttribute("pet", pet); + return "petForm"; + } + + // ... + + } +---- + +Parameters using this annotation are required by default, but you can specify that a +parameter is optional by setting ``@RequestParam``'s `required` flag to `false` or +declare the argument with a `java.util.Optional` wrapper. + +Type conversion is applied automatically if the target method parameter type is not +`String`. See <>. + +When an `@RequestParam` annotation is declared as `Map` or +`MultiValueMap` argument, the map is populated with all request +parameters. + + +[[webflux-ann-requestheader]] +==== @RequestHeader +[.small]#<># + +Use the `@RequestHeader` annotation to bind a request header to a method argument in a +controller. + +Given request with headers: + +[literal] +[subs="verbatim,quotes"] +---- +Host localhost:8080 +Accept text/html,application/xhtml+xml,application/xml;q=0.9 +Accept-Language fr,en-gb;q=0.7,en;q=0.3 +Accept-Encoding gzip,deflate +Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 +Keep-Alive 300 +---- + +The following gets the value of the `Accept-Encoding` and `Keep-Alive` headers: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @GetMapping("/demo") + public void handle( + **@RequestHeader("Accept-Encoding")** String encoding, + **@RequestHeader("Keep-Alive")** long keepAlive) { + //... + } +---- + +Type conversion is applied automatically if the target method parameter type is not +`String`. See <>. + +When an `@RequestHeader` annotation is used on a `Map`, +`MultiValueMap`, or `HttpHeaders` argument, the map is populated +with all header values. + +[TIP] +==== +Built-in support is available for converting a comma-separated string into an +array/collection of strings or other types known to the type conversion system. For +example a method parameter annotated with `@RequestHeader("Accept")` may be of type +`String` but also `String[]` or `List`. +==== + + +[[webflux-ann-cookievalue]] +==== @CookieValue +[.small]#<># + +Use the `@CookieValue` annotation to bind the value of an HTTP cookie to a method argument +in a controller. + +Given request with the following cookie: + +[literal] +[subs="verbatim,quotes"] +---- +JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 +---- + +The following code sample demonstrates how to get the cookie value: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @GetMapping("/demo") + public void handle(**@CookieValue("JSESSIONID")** String cookie) { + //... + } +---- + +Type conversion is applied automatically if the target method parameter type is not +`String`. See <>. + + + +[[webflux-ann-initbinder]] +=== Binder Methods +[.small]#<># + +`@InitBinder` methods in an `@Controller` or `@ControllerAdvice` class can be used to +customize type conversion for method arguments that represent String-based request values +(e.g. request parameters, path variables, headers, cookies, and others). Type conversion +also applies during data binding of request parameters onto `@ModelAttribute` arguments +(i.e. command objects). + +`@InitBinder` methods can register controller-specific `java.bean.PropertyEditor`, or +Spring `Converter` and `Formatter` components. In addition, the +<> can be used to register `Converter` and +`Formatter` types in a globally shared `FormattingConversionService`. + +`@InitBinder` methods support many of the same arguments that a `@RequestMapping` methods +do, except for `@ModelAttribute` (command object) arguments. Typically they're are declared +with a `WebDataBinder` argument, for registrations, and a `void` return value. +Below is an example: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class FormController { + + **@InitBinder** + public void initBinder(WebDataBinder binder) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + dateFormat.setLenient(false); + binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); + } + + // ... + } +---- + +Alternatively when using a `Formatter`-based setup through a shared +`FormattingConversionService`, you could re-use the same approach and register +controller-specific ``Formatter``'s: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Controller + public class FormController { + + **@InitBinder** + protected void initBinder(WebDataBinder binder) { + binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd")); + } + + // ... + } +---- + + include::webflux-functional.adoc[leveloffset=+1] diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index 7c3d7ba7452..9ace8810eea 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -1164,7 +1164,7 @@ public class OwnerController { URI variables are automatically converted to the appropriate type or`TypeMismatchException` is raised. Simple types -- `int`, `long`, `Date`, are supported by default and you can register support for any other data type. -See <> and <>. +See <> and <>. URI variables can be named explicitly -- e.g. `@PathVariable("customId")`, but you can leave that detail out if the names are the same and your code is compiled with debugging @@ -1597,6 +1597,10 @@ method argument type. See <>. |For access to request headers. Header values are converted to the declared method argument type. See <>. +|`@CookieValue` +|For access to cookies. Cookies values are converted to the declared method argument +type. See <>. + |`@RequestBody` |For access to the HTTP request body. Body content is converted to the declared method argument type using ``HttpMessageConverter``s. See <>. @@ -1739,11 +1743,27 @@ class name of the return type. |=== +[[mvc-ann-typeconversion]] +==== Type Conversion +[.small]#<># + +Some annotated controller method arguments that represent String-based request input -- e.g. +`@RequestParam`, `@RequestHeader`, `@PathVariable`, `@MatrixVariable`, and `@CookieValue`, +may require type conversion if the argument is declared as something other than `String`. + +For such cases type conversion is automatically applied based on the configured converters. +By default simple types such as `int`, `long`, `Date`, etc. are supported. Type conversion +can be customized through a `WebDataBinder`, see <>, or by registering +`Formatters` with the `FormattingConversionService`, see +<>. + + [[mvc-ann-requestparam]] ==== @RequestParam +[.small]#<># -Use the `@RequestParam` annotation to bind request parameters to a method parameter in -your controller. +Use the `@RequestParam` annotation to bind Servlet request parameters (i.e. query +parameters or form data) to a method argument in a controller. The following code snippet shows the usage: @@ -1752,13 +1772,12 @@ The following code snippet shows the usage: ---- @Controller @RequestMapping("/pets") - @SessionAttributes("pet") public class EditPetForm { // ... @GetMapping - public String setupForm(**@RequestParam("petId") int petId**, ModelMap model) { + public String setupForm(**@RequestParam("petId") int petId**, Model model) { Pet pet = this.clinic.loadPet(petId); model.addAttribute("pet", pet); return "petForm"; @@ -1770,36 +1789,25 @@ The following code snippet shows the usage: ---- Parameters using this annotation are required by default, but you can specify that a -parameter is optional by setting ``@RequestParam``'s `required` attribute to `false` -(e.g., `@RequestParam(name="id", required=false)`). +parameter is optional by setting ``@RequestParam``'s `required` flag to `false` or +declare the argument with a `java.util.Optional` wrapper. Type conversion is applied automatically if the target method parameter type is not `String`. See <>. -When an `@RequestParam` annotation is used on a `Map` or +When an `@RequestParam` annotation is declared as `Map` or `MultiValueMap` argument, the map is populated with all request parameters. -[[mvc-ann-typeconversion]] -==== Type Conversion - -String-based values extracted from the request including request parameters, path -variables, request headers, and cookie values may need to be converted to the target -type of the method parameter or field (e.g., binding a request parameter to a field in -an `@ModelAttribute` parameter) they're bound to. If the target type is not `String`, -Spring automatically converts to the appropriate type. All simple types such as int, -long, Date, etc. are supported. You can further customize the conversion process through -a `WebDataBinder`, see <>, or by registering `Formatters` with -the `FormattingConversionService`, see <>. - - [[mvc-ann-requestheader]] ==== @RequestHeader +[.small]#<># -The `@RequestHeader` annotation allows a method parameter to be bound to a request header. +Use the `@RequestHeader` annotation to bind a request header to a method argument in a +controller. -Here is a sample request header: +Given request with headers: [literal] [subs="verbatim,quotes"] @@ -1812,21 +1820,21 @@ Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 300 ---- -The following code sample demonstrates how to get the value of the `Accept-Encoding` and -`Keep-Alive` headers: +The following gets the value of the `Accept-Encoding` and `Keep-Alive` headers: [source,java,indent=0] [subs="verbatim,quotes"] ---- - @RequestMapping("/displayHeaderInfo.do") - public void displayHeaderInfo(**@RequestHeader("Accept-Encoding")** String encoding, + @GetMapping("/demo") + public void handle( + **@RequestHeader("Accept-Encoding")** String encoding, **@RequestHeader("Keep-Alive")** long keepAlive) { //... } ---- -Type conversion is applied automatically if the method parameter is not `String`. See -<>. +Type conversion is applied automatically if the target method parameter type is not +`String`. See <>. When an `@RequestHeader` annotation is used on a `Map`, `MultiValueMap`, or `HttpHeaders` argument, the map is populated @@ -1843,11 +1851,12 @@ example a method parameter annotated with `@RequestHeader("Accept")` may be of t [[mvc-ann-cookievalue]] ==== @CookieValue +[.small]#<># -The `@CookieValue` annotation allows a method parameter to be bound to the value of an -HTTP cookie. +Use the `@CookieValue` annotation to bind the value of an HTTP cookie to a method argument +in a controller. -Let us consider that the following cookie has been received with an http request: +Given request with the following cookie: [literal] [subs="verbatim,quotes"] @@ -1855,13 +1864,13 @@ Let us consider that the following cookie has been received with an http request JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84 ---- -The following code sample demonstrates how to get the value of the `JSESSIONID` cookie: +The following code sample demonstrates how to get the cookie value: [source,java,indent=0] [subs="verbatim,quotes"] ---- - @RequestMapping("/displayHeaderInfo.do") - public void displayHeaderInfo(**@CookieValue("JSESSIONID")** String cookie) { + @GetMapping("/demo") + public void handle(**@CookieValue("JSESSIONID")** String cookie) { //... } ---- @@ -1925,7 +1934,7 @@ name. Matching fields are populated after type conversion (from String to the ta field type) has been applied where necessary. Data binding and validation are covered in <>. Customizing the data binding process for a controller level is covered in -<>. +<>. As a result of data binding there may be errors such as missing required fields or type conversion errors. To check for such errors add a `BindingResult` argument immediately @@ -2628,34 +2637,33 @@ conventions instead, much like for methods returning `void` -- see <># -To customize request parameter binding with PropertyEditors through Spring's -`WebDataBinder`, you can use `@InitBinder`-annotated methods within your controller, -`@InitBinder` methods within an `@ControllerAdvice` class, or provide a custom -`WebBindingInitializer`. See the <> section for more details. +`@InitBinder` methods in an `@Controller` or `@ControllerAdvice` class can be used to +customize type conversion for method arguments that represent String-based request values +(e.g. request parameters, path variables, headers, cookies, and others). Type conversion +also applies during data binding of request parameters onto `@ModelAttribute` arguments +(i.e. command objects). -Annotating controller methods with `@InitBinder` allows you to configure web data -binding directly within your controller class. `@InitBinder` identifies methods that -initialize the `WebDataBinder` that will be used to populate command and form object -arguments of annotated handler methods. +`@InitBinder` methods can register controller-specific `java.bean.PropertyEditor`, or +Spring `Converter` and `Formatter` components. In addition, the +<> can be used to register `Converter` and `Formatter` +types in a globally shared `FormattingConversionService`. -Such init-binder methods support all arguments that `@RequestMapping` methods support, -except for command/form objects and corresponding validation result objects. Init-binder -methods must not have a return value. Thus, they are usually declared as `void`. -Typical arguments include `WebDataBinder` in combination with `WebRequest` or -`java.util.Locale`, allowing code to register context-specific editors. -The following example demonstrates the use of `@InitBinder` to configure a -`CustomDateEditor` for all `java.util.Date` form properties. +`@InitBinder` methods support many of the same arguments that a `@RequestMapping` methods +do, except for `@ModelAttribute` (command object) arguments. Typically they're are declared +with a `WebDataBinder` argument, for registrations, and a `void` return value. +Below is an example: [source,java,indent=0] [subs="verbatim,quotes"] ---- @Controller - public class MyFormController { + public class FormController { **@InitBinder** - protected void initBinder(WebDataBinder binder) { + public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); @@ -2665,17 +2673,15 @@ The following example demonstrates the use of `@InitBinder` to configure a } ---- -Alternatively, as of Spring 4.2, consider using `addCustomFormatter` to specify -`Formatter` implementations instead of `PropertyEditor` instances. This is -particularly useful if you happen to have a `Formatter`-based setup in a shared -`FormattingConversionService` as well, with the same approach to be reused for -controller-specific tweaking of the binding rules. +Alternatively when using a `Formatter`-based setup through a shared +`FormattingConversionService`, you could re-use the same approach and register +controller-specific ``Formatter``'s: [source,java,indent=0] [subs="verbatim,quotes"] ---- @Controller - public class MyFormController { + public class FormController { **@InitBinder** protected void initBinder(WebDataBinder binder) {