Migrate to Asciidoctor Tabs

This commit is contained in:
Rob Winch
2023-04-20 16:21:36 -05:00
committed by rstoyanchev
parent 71154fd16b
commit 39146f9066
243 changed files with 7124 additions and 1779 deletions

View File

@@ -25,8 +25,11 @@ By default, `@ControllerAdvice` methods apply to every request (that is, all con
but you can narrow that down to a subset of controllers by using attributes on the
annotation, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
@@ -41,8 +44,9 @@ annotation, as the following example shows:
public class ExampleAdvice3 {}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = [RestController::class])
@@ -56,6 +60,7 @@ annotation, as the following example shows:
@ControllerAdvice(assignableTypes = [ControllerInterface::class, AbstractController::class])
public class ExampleAdvice3 {}
----
======
The selectors in the preceding example are evaluated at runtime and may negatively impact
performance if used extensively. See the

View File

@@ -7,8 +7,11 @@
`@ExceptionHandler` methods to handle exceptions from controller methods. The following
example includes such a handler method:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
public class SimpleController {
@@ -21,6 +24,7 @@ example includes such a handler method:
}
}
----
======
<1> Declaring an `@ExceptionHandler`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -22,8 +22,11 @@ with a `WebDataBinder` argument, for registrations, and a `void` return value.
The following example uses the `@InitBinder` annotation:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
public class FormController {
@@ -38,6 +41,7 @@ The following example uses the `@InitBinder` annotation:
// ...
}
----
======
<1> Using the `@InitBinder` annotation.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -64,8 +68,11 @@ Alternatively, when using a `Formatter`-based setup through a shared
controller-specific `Formatter` instances, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
public class FormController {
@@ -78,6 +85,7 @@ controller-specific `Formatter` instances, as the following example shows:
// ...
}
----
======
<1> Adding a custom formatter (a `DateFormatter`, in this case).
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -15,14 +15,18 @@ JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84
The following code sample demonstrates how to get the cookie value:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/demo")
public void handle(@CookieValue("JSESSIONID") String cookie) { // <1>
//...
}
----
======
<1> Get the cookie value.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -7,21 +7,27 @@
container object that exposes request headers and the body. The following example uses an
`HttpEntity`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/accounts")
public void handle(HttpEntity<Account> entity) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/accounts")
fun handle(entity: HttpEntity<Account>) {
// ...
}
----
======

View File

@@ -13,8 +13,11 @@ which allows rendering only a subset of all fields in an `Object`. To use it wit
`@ResponseBody` or `ResponseEntity` controller methods, you can use Jackson's
`@JsonView` annotation to activate a serialization view class, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@RestController
public class UserController {
@@ -54,8 +57,9 @@ which allows rendering only a subset of all fields in an `Object`. To use it wit
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@RestController
class UserController {
@@ -75,6 +79,7 @@ which allows rendering only a subset of all fields in an `Object`. To use it wit
interface WithPasswordView : WithoutPasswordView
}
----
======
NOTE: `@JsonView` allows an array of view classes but you can only specify only one per
controller method. Use a composite interface if you need to activate multiple views.

View File

@@ -19,8 +19,11 @@ to mask variable content. That said, if you want to access matrix variables from
controller method, you need to add a URI variable to the path segment where matrix
variables are expected. The following example shows how to do so:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// GET /pets/42;q=11;r=22
@@ -31,8 +34,10 @@ variables are expected. The following example shows how to do so:
// q == 11
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// GET /pets/42;q=11;r=22
@@ -43,14 +48,18 @@ variables are expected. The following example shows how to do so:
// q == 11
}
----
======
Given that all path segments can contain matrix variables, you may sometimes need to
disambiguate which path variable the matrix variable is expected to be in,
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// GET /owners/42;q=11/pets/21;q=22
@@ -63,8 +72,10 @@ as the following example shows:
// q2 == 22
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(
@@ -75,12 +86,16 @@ as the following example shows:
// q2 == 22
}
----
======
You can define a matrix variable may be defined as optional and specify a default value
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// GET /pets/42
@@ -90,8 +105,10 @@ as the following example shows:
// q == 1
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// GET /pets/42
@@ -101,11 +118,15 @@ as the following example shows:
// q == 1
}
----
======
To get all matrix variables, use a `MultiValueMap`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23
@@ -118,8 +139,10 @@ To get all matrix variables, use a `MultiValueMap`, as the following example sho
// petMatrixVars: ["q" : 22, "s" : 23]
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
// GET /owners/42;q=11;r=12/pets/21;q=22;s=23
@@ -132,5 +155,6 @@ To get all matrix variables, use a `MultiValueMap`, as the following example sho
// petMatrixVars: ["q" : 22, "s" : 23]
}
----
======

View File

@@ -9,12 +9,16 @@ the values of query parameters and form fields whose names match to field names.
referred to as data binding, and it saves you from having to deal with parsing and
converting individual query parameters and form fields. The following example binds an instance of `Pet`:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute Pet pet) { } // <1>
----
======
<1> Bind an instance of `Pet`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -45,8 +49,11 @@ Data binding can result in errors. By default, a `WebExchangeBindException` is r
to check for such errors in the controller method, you can add a `BindingResult` argument
immediately next to the `@ModelAttribute`, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result) { <1>
@@ -56,6 +63,7 @@ immediately next to the `@ModelAttribute`, as the following example shows:
// ...
}
----
======
<1> Adding a `BindingResult`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -76,8 +84,11 @@ You can automatically apply validation after data binding by adding the
xref:core/validation/beanvalidation.adoc[Bean Validation] and
xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following example uses the `@Valid` annotation:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public String processSubmit(@Valid @ModelAttribute("pet") Pet pet, BindingResult result) { // <1>
@@ -87,6 +98,7 @@ xref:web/webmvc/mvc-config/validation.adoc[Spring validation]). The following ex
// ...
}
----
======
<1> Using `@Valid` on a model attribute argument.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -110,8 +122,11 @@ argument, you must declare the `@ModelAttribute` argument before it without a re
type wrapper, as shown earlier. Alternatively, you can handle any errors through the
reactive type, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
public Mono<String> processSubmit(@Valid @ModelAttribute("pet") Mono<Pet> petMono) {
@@ -124,8 +139,10 @@ reactive type, as the following example shows:
});
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/owners/{ownerId}/pets/{petId}/edit")
fun processSubmit(@Valid @ModelAttribute("pet") petMono: Mono<Pet>): Mono<String> {
@@ -138,6 +155,7 @@ reactive type, as the following example shows:
}
}
----
======
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

View File

@@ -9,8 +9,11 @@ is through data binding to a xref:web/webflux/controller/ann-methods/modelattrib
as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
class MyForm {
@@ -32,8 +35,10 @@ as the following example shows:
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
class MyForm(
val name: String,
@@ -49,6 +54,7 @@ as the following example shows:
}
----
======
--
You can also submit multipart requests from non-browser clients in a RESTful service
@@ -77,8 +83,11 @@ Content-Transfer-Encoding: 8bit
You can access individual parts with `@RequestPart`, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/")
public String handle(@RequestPart("meta-data") Part metadata, // <1>
@@ -86,6 +95,7 @@ You can access individual parts with `@RequestPart`, as the following example sh
// ...
}
----
======
<1> Using `@RequestPart` to get the metadata.
<2> Using `@RequestPart` to get the file.
@@ -107,14 +117,18 @@ To deserialize the raw part content (for example, to JSON -- similar to `@Reques
you can declare a concrete target `Object`, instead of `Part`, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/")
public String handle(@RequestPart("meta-data") MetaData metadata) { // <1>
// ...
}
----
======
<1> Using `@RequestPart` to get the metadata.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -136,8 +150,11 @@ in the controller method by declaring the argument with an async wrapper and the
error related operators:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/")
public String handle(@Valid @RequestPart("meta-data") Mono<MetaData> metadata) {
@@ -145,28 +162,34 @@ error related operators:
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/")
fun handle(@Valid @RequestPart("meta-data") metadata: MetaData): String {
// ...
}
----
======
--
To access all multipart data as a `MultiValueMap`, you can use `@RequestBody`,
as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/")
public String handle(@RequestBody Mono<MultiValueMap<String, Part>> parts) { // <1>
// ...
}
----
======
<1> Using `@RequestBody`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -196,8 +219,11 @@ when uploading. If the file is large enough to be split across multiple buffers,
For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/")
public void handle(@RequestBody Flux<PartEvent> allPartsEvents) { <1>
@@ -224,6 +250,7 @@ For example:
}));
}
----
======
<1> Using `@RequestBody`.
<2> The final `PartEvent` for a particular part will have `isLast()` set to `true`, and can be
followed by additional events belonging to subsequent parts.

View File

@@ -7,14 +7,18 @@ Similarly to `@SessionAttribute`, you can use the `@RequestAttribute` annotation
access pre-existing request attributes created earlier (for example, by a `WebFilter`),
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/")
public String handle(@RequestAttribute Client client) { <1>
// ...
}
----
======
<1> Using `@RequestAttribute`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -7,8 +7,11 @@ You can use the `@RequestBody` annotation to have the request body read and dese
`Object` through an xref:web/webflux/reactive-spring.adoc#webflux-codecs[HttpMessageReader].
The following example uses a `@RequestBody` argument:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/accounts")
public void handle(@RequestBody Account account) {
@@ -16,34 +19,42 @@ The following example uses a `@RequestBody` argument:
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/accounts")
fun handle(@RequestBody account: Account) {
// ...
}
----
======
Unlike Spring MVC, in WebFlux, the `@RequestBody` method argument supports reactive types
and fully non-blocking reading and (client-to-server) streaming.
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/accounts")
public void handle(@RequestBody Mono<Account> account) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/accounts")
fun handle(@RequestBody accounts: Flow<Account>) {
// ...
}
----
======
You can use the xref:web/webflux/config.adoc#webflux-config-message-codecs[HTTP message codecs] option of the xref:web/webflux/dispatcher-handler.adoc#webflux-framework-config[WebFlux Config] to
configure or customize message readers.
@@ -55,21 +66,27 @@ The exception contains a `BindingResult` with error details and can be handled i
controller method by declaring the argument with an async wrapper and then using error
related operators:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping("/accounts")
public void handle(@Valid @RequestBody Mono<Account> account) {
// use one of the onError* operators...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/accounts")
fun handle(@Valid @RequestBody account: Mono<Account>) {
// ...
}
----
======

View File

@@ -21,8 +21,11 @@ Keep-Alive 300
The following example gets the value of the `Accept-Encoding` and `Keep-Alive` headers:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/demo")
public void handle(
@@ -31,6 +34,7 @@ The following example gets the value of the `Accept-Encoding` and `Keep-Alive` h
//...
}
----
======
<1> Get the value of the `Accept-Encoding` header.
<2> Get the value of the `Keep-Alive` header.

View File

@@ -6,8 +6,11 @@
You can use the `@RequestParam` annotation to bind query parameters to a method argument in a
controller. The following code snippet shows the usage:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
@RequestMapping("/pets")
@@ -25,6 +28,7 @@ controller. The following code snippet shows the usage:
// ...
}
----
======
<1> Using `@RequestParam`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -7,8 +7,11 @@ You can use the `@ResponseBody` annotation on a method to have the return serial
to the response body through an xref:web/webflux/reactive-spring.adoc#webflux-codecs[HttpMessageWriter]. The following
example shows how to do so:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/accounts/{id}")
@ResponseBody
@@ -16,8 +19,10 @@ example shows how to do so:
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/accounts/{id}")
@ResponseBody
@@ -25,6 +30,7 @@ example shows how to do so:
// ...
}
----
======
`@ResponseBody` is also supported at the class level, in which case it is inherited by
all controller methods. This is the effect of `@RestController`, which is nothing more

View File

@@ -5,8 +5,11 @@
`ResponseEntity` is like xref:web/webflux/controller/ann-methods/responsebody.adoc[`@ResponseBody`] but with status and headers. For example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/something")
public ResponseEntity<String> handle() {
@@ -15,8 +18,10 @@
return ResponseEntity.ok().eTag(etag).body(body);
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/something")
fun handle(): ResponseEntity<String> {
@@ -25,6 +30,7 @@
return ResponseEntity.ok().eTag(etag).build(body)
}
----
======
WebFlux supports using a single value xref:web-reactive.adoc#webflux-reactive-libraries[reactive type] to
produce the `ResponseEntity` asynchronously, and/or single and multi-value reactive types

View File

@@ -7,14 +7,18 @@ If you need access to pre-existing session attributes that are managed globally
(that is, outside the controller -- for example, by a filter) and may or may not be present,
you can use the `@SessionAttribute` annotation on a method parameter, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/")
public String handle(@SessionAttribute User user) { // <1>
// ...
}
----
======
<1> Using `@SessionAttribute`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]

View File

@@ -11,8 +11,11 @@ requests to access.
Consider the following example:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
@SessionAttributes("pet") <1>
@@ -20,6 +23,7 @@ Consider the following example:
// ...
}
----
======
<1> Using the `@SessionAttributes` annotation.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -38,8 +42,11 @@ it is automatically promoted to and saved in the `WebSession`. It remains there
another controller method uses a `SessionStatus` method argument to clear the storage,
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
@SessionAttributes("pet") // <1>
@@ -58,6 +65,7 @@ as the following example shows:
}
}
----
======
<1> Using the `@SessionAttributes` annotation.
<2> Using a `SessionStatus` variable.

View File

@@ -24,8 +24,11 @@ related to the request body).
The following example uses a `@ModelAttribute` method:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@ModelAttribute
public void populateModel(@RequestParam String number, Model model) {
@@ -33,8 +36,10 @@ The following example uses a `@ModelAttribute` method:
// add more ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@ModelAttribute
fun populateModel(@RequestParam number: String, model: Model) {
@@ -42,25 +47,32 @@ The following example uses a `@ModelAttribute` method:
// add more ...
}
----
======
The following example adds one attribute only:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@ModelAttribute
public Account addAccount(@RequestParam String number) {
return accountRepository.findAccount(number);
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@ModelAttribute
fun addAccount(@RequestParam number: String): Account {
return accountRepository.findAccount(number);
}
----
======
NOTE: When a name is not explicitly specified, a default name is chosen based on the type,
as explained in the javadoc for {api-spring-framework}/core/Conventions.html[`Conventions`].
@@ -73,8 +85,11 @@ attributes can be transparently resolved (and the model updated) to their actual
at the time of `@RequestMapping` invocation, provided a `@ModelAttribute` argument is
declared without a wrapper, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@ModelAttribute
public void addAccount(@RequestParam String number) {
@@ -87,8 +102,10 @@ declared without a wrapper, as the following example shows:
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
import org.springframework.ui.set
@@ -103,6 +120,7 @@ declared without a wrapper, as the following example shows:
// ...
}
----
======
In addition, any model attributes that have a reactive type wrapper are resolved to their
@@ -115,8 +133,11 @@ controllers, unless the return value is a `String` that would otherwise be inter
as a view name. `@ModelAttribute` can also help to customize the model attribute name,
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/accounts/{id}")
@ModelAttribute("myAccount")
@@ -125,8 +146,10 @@ as the following example shows:
return account;
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/accounts/{id}")
@ModelAttribute("myAccount")
@@ -135,6 +158,7 @@ as the following example shows:
return account
}
----
======

View File

@@ -23,8 +23,11 @@ using `@RequestMapping`, which, by default, matches to all HTTP methods. At the
The following example uses type and method level mappings:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@RestController
@RequestMapping("/persons")
@@ -42,8 +45,10 @@ The following example uses type and method level mappings:
}
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@RestController
@RequestMapping("/persons")
@@ -61,6 +66,7 @@ The following example uses type and method level mappings:
}
}
----
======
[[webflux-ann-requestmapping-uri-templates]]
@@ -106,29 +112,38 @@ You can map requests by using glob patterns and wildcards:
Captured URI variables can be accessed with `@PathVariable`, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
// ...
}
----
======
--
You can declare URI variables at the class and method levels, as the following example shows:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Controller
@RequestMapping("/owners/{ownerId}") // <1>
@@ -140,6 +155,7 @@ You can declare URI variables at the class and method levels, as the following e
}
}
----
======
<1> Class-level URI mapping.
<2> Method-level URI mapping.
@@ -179,22 +195,28 @@ syntax: `{varName:regex}`. For example, given a URL of `/spring-web-3.0.5.jar`,
extracts the name, version, and file extension:
--
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String version, @PathVariable String ext) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
fun handle(@PathVariable version: String, @PathVariable ext: String) {
// ...
}
----
======
--
URI path patterns can also have embedded `${...}` placeholders that are resolved on startup
@@ -234,22 +256,28 @@ sorted last instead. If two patterns are both catch-all, the longer is chosen.
You can narrow the request mapping based on the `Content-Type` of the request,
as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@PostMapping(path = "/pets", consumes = "application/json")
public void addPet(@RequestBody Pet pet) {
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@PostMapping("/pets", consumes = ["application/json"])
fun addPet(@RequestBody pet: Pet) {
// ...
}
----
======
The consumes attribute also supports negation expressions -- for example, `!text/plain` means any
content type other than `text/plain`.
@@ -269,8 +297,11 @@ TIP: `MediaType` provides constants for commonly used media types -- for example
You can narrow the request mapping based on the `Accept` request header and the list of
content types that a controller method produces, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping(path = "/pets/{petId}", produces = "application/json")
@ResponseBody
@@ -278,8 +309,10 @@ content types that a controller method produces, as the following example shows:
// ...
}
----
Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin
----
@GetMapping("/pets/{petId}", produces = ["application/json"])
@ResponseBody
@@ -287,6 +320,7 @@ content types that a controller method produces, as the following example shows:
// ...
}
----
======
The media type can specify a character set. Negated expressions are supported -- for example,
`!text/plain` means any content type other than `text/plain`.
@@ -307,14 +341,18 @@ You can narrow request mappings based on query parameter conditions. You can tes
presence of a query parameter (`myParam`), for its absence (`!myParam`), or for a
specific value (`myParam=myValue`). The following examples tests for a parameter with a value:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping(path = "/pets/{petId}", params = "myParam=myValue") // <1>
public void findPet(@PathVariable String petId) {
// ...
}
----
======
<1> Check that `myParam` equals `myValue`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -329,14 +367,18 @@ specific value (`myParam=myValue`). The following examples tests for a parameter
You can also use the same with request header conditions, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@GetMapping(path = "/pets/{petId}", headers = "myHeader=myValue") // <1>
public void findPet(@PathVariable String petId) {
// ...
}
----
======
<1> Check that `myHeader` equals `myValue`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@@ -401,8 +443,11 @@ You can programmatically register Handler methods, which can be used for dynamic
registrations or for advanced cases, such as different instances of the same handler
under different URLs. The following example shows how to do so:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Configuration
public class MyConfig {
@@ -421,6 +466,7 @@ under different URLs. The following example shows how to do so:
}
----
======
<1> Inject target handlers and the handler mapping for controllers.
<2> Prepare the request mapping metadata.
<3> Get the handler method.

View File

@@ -12,8 +12,11 @@ a web component.
To enable auto-detection of such `@Controller` beans, you can add component scanning to
your Java configuration, as the following example shows:
[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java
----
@Configuration
@ComponentScan("org.example.web") // <1>
@@ -22,6 +25,7 @@ your Java configuration, as the following example shows:
// ...
}
----
======
<1> Scan the `org.example.web` package.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]