Revise docs for server use of `@HttpExchange`
Closes gh-30980
This commit is contained in:
parent
6630b16771
commit
5115684baf
|
@ -363,12 +363,13 @@ If necessary the `Content-Type` may also be set explicitly.
|
|||
[[rest-http-interface]]
|
||||
== HTTP Interface
|
||||
|
||||
The Spring Framework lets you define an HTTP service as a Java interface with annotated
|
||||
methods for HTTP exchanges. You can then generate a proxy that implements this interface
|
||||
and performs the exchanges. This helps to simplify HTTP remote access which often
|
||||
involves a facade that wraps the details of using the underlying HTTP client.
|
||||
The Spring Framework lets you define an HTTP service as a Java interface with
|
||||
`@HttpExchange` methods. You can pass such an interface to `HttpServiceProxyFactory`
|
||||
to create a proxy which performs requests through an HTTP client such as `RestClient`
|
||||
or `WebClient`. You can also implement the interface from an `@Controller` for server
|
||||
request handling.
|
||||
|
||||
One, declare an interface with `@HttpExchange` methods:
|
||||
Start by creating the interface with `@HttpExchange` methods:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
|
@ -382,19 +383,9 @@ One, declare an interface with `@HttpExchange` methods:
|
|||
}
|
||||
----
|
||||
|
||||
Two, create a proxy that will perform the declared HTTP exchanges,
|
||||
either using `WebClient`:
|
||||
Now you can create a proxy that performs requests when methods are called.
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
|
||||
WebClientAdapter adapter = WebClientAdapter.forClient(webClient)
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
|
||||
|
||||
RepositoryService service = factory.createClient(RepositoryService.class);
|
||||
----
|
||||
|
||||
using `RestClient`:
|
||||
For `RestClient`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
|
@ -405,7 +396,18 @@ using `RestClient`:
|
|||
RepositoryService service = factory.createClient(RepositoryService.class);
|
||||
----
|
||||
|
||||
or using `RestTemplate`:
|
||||
For `WebClient`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
|
||||
WebClientAdapter adapter = WebClientAdapter.forClient(webClient)
|
||||
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
|
||||
|
||||
RepositoryService service = factory.createClient(RepositoryService.class);
|
||||
----
|
||||
|
||||
For `RestTemplate`:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
|
|
|
@ -871,7 +871,7 @@ interaction type(s):
|
|||
As an alternative to `@MessageMapping`, you can also handle requests with
|
||||
`@RSocketExchange` methods. Such methods are declared on an
|
||||
xref:rsocket-interface[RSocket Interface] and can be used as a requester via
|
||||
`RSocketServiceProxyFactory` or as a responder.
|
||||
`RSocketServiceProxyFactory` or implemented by a responder.
|
||||
|
||||
For example, to handle requests as a responder:
|
||||
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
[[webflux-ann-httpexchange]]
|
||||
= HttpExchange
|
||||
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc[See equivalent in the Servlet stack]#
|
||||
|
||||
Similarly to
|
||||
xref:web/webflux/controller/ann-requestmapping.adoc[`@RequestMapping`],
|
||||
you can use the `@HttpExchange` annotation to map requests to controllers
|
||||
methods. However, while `@RequestMapping` is only supported on the server side, `@HttpExchange` can be used both to create a server-side mapping and
|
||||
xref:integration/rest-clients.adoc#rest-http-interface[an HTTP
|
||||
Interface Client] that allows making requests.
|
||||
|
||||
`@HttpExchange` has various attributes to match by URL, HTTP method, and media
|
||||
types. You can use it at the class level to express shared mappings or at the
|
||||
method level to narrow down to a specific endpoint mapping.
|
||||
|
||||
There are also HTTP method specific shortcut variants of `@HttpExchange`:
|
||||
|
||||
* `@GetExchange`
|
||||
* `@PostExchange`
|
||||
* `@PutExchange`
|
||||
* `@DeleteExchange`
|
||||
* `@PatchExchange`
|
||||
|
||||
// TODO
|
||||
The shortcuts are xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-composed[Custom Annotations] that are provided
|
||||
because, arguably, most controller methods should be mapped to a specific
|
||||
HTTP method versus using `@HttpExchange`, which, by default, matches
|
||||
to all HTTP methods.
|
||||
An `@HttpExchange` is still needed at the class level to express shared mappings.
|
||||
|
||||
The following example has type and method level mappings:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
public Person getPerson(@PathVariable Long id) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public void add(@RequestBody Person person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
fun getPerson(@PathVariable id: Long): Person {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun add(@RequestBody person: Person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
`@HttpExhange` supports a very similar method signature to `@MessageMapping`,
|
||||
however, since it needs to be suitable both for requester and responder use,
|
||||
there are slight differences.
|
||||
|
||||
[[webflux-ann-httpexchange-uri-templates]]
|
||||
== URI patterns
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-uri-templates[See equivalent in the Servlet stack]#
|
||||
|
||||
URI patterns resolution support is very similar to the one offered by xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-uri-templates[`@RequestMapping`], with the difference
|
||||
that while `@RequestMapping` accepts a `String` array as its `value` or `path`
|
||||
parameter that is used to specify the URI patterns, only a single `String` can be passed
|
||||
as the `value` of `@HttpExchange`.
|
||||
|
||||
[[webflux-ann-httpexchange-contenttype]]
|
||||
== Consumable Media Types
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-contenttype[See equivalent in the Servlet stack]#
|
||||
|
||||
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"]
|
||||
----
|
||||
@PostExchange(path = "/pets", contentType = "application/json") // <1>
|
||||
public void addPet(@RequestBody Pet pet) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using a `contentType` attribute to narrow the mapping by the content type.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@PostExchange("/pets", contentType = "application/json") // <1>
|
||||
fun addPet(@RequestBody pet: Pet) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using a `contentType` attribute to narrow the mapping by the content type.
|
||||
======
|
||||
|
||||
The `contentType` attribute accepts a single `String` as the attribute value.
|
||||
|
||||
You can also declare a shared `contentType` attribute at the class level.
|
||||
Unlike most other request-mapping attributes, however, when used at the
|
||||
class level, a method-level `contentType` attribute overrides rather than
|
||||
extends the class-level declaration.
|
||||
|
||||
TIP: `MediaType` provides constants for commonly used media types, such as
|
||||
`APPLICATION_JSON_VALUE` and `APPLICATION_XML_VALUE`.
|
||||
|
||||
|
||||
[[webflux-ann-httpexchange-accept]]
|
||||
== Producible Media Types
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-accept[See equivalent in the Servlet stack]#
|
||||
|
||||
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"]
|
||||
----
|
||||
@GetExchange(path = "/pets/{petId}", accept = "application/json") // <1>
|
||||
@ResponseBody
|
||||
public Pet getPet(@PathVariable String petId) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using an `accept` attribute to narrow the mapping by the content type that
|
||||
can be served.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@GetExchange("/pets/{petId}", accept = ["application/json"]) // <1>
|
||||
@ResponseBody
|
||||
fun getPet(@PathVariable petId: String): Pet {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using an `accept` attribute to narrow the mapping by the content type that
|
||||
can be served.
|
||||
======
|
||||
|
||||
The `accept` attribute accepts a `String` array as the attribute value.
|
||||
|
||||
You can declare a shared `accept` attribute at the class level. Unlike most
|
||||
other request-mapping attributes, however, when used at the class level,
|
||||
a method-level `accept` attribute
|
||||
overrides rather than extends the class-level declaration.
|
||||
|
||||
TIP: `MediaType` provides constants for commonly used media types, such as
|
||||
`APPLICATION_JSON_VALUE` and `APPLICATION_XML_VALUE`.
|
||||
|
||||
|
||||
[[webflux-ann-httpexchange-params-and-headers]]
|
||||
== Parameters, headers
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-params-and-headers[See equivalent in the Servlet stack]#
|
||||
|
||||
You can narrow request mappings based on request parameter and headers
|
||||
conditions. It is supported for `@HttpExchange` in the same way as in xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-params-and-headers[`@RequestMapping` parameters and headers support].
|
||||
|
||||
|
||||
[[webflux-ann-httpexchange-head-options]]
|
||||
== HTTP HEAD, OPTIONS
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-head-options[See equivalent in the Servlet stack]#
|
||||
|
||||
The support of `HTTP HEAD` and `HTTP OPTIONS` in `@HttpExchange` annotated
|
||||
controllers is the same xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-head-options[
|
||||
as in `@RequestMapping` annotated controllers].
|
||||
|
||||
[[webflux-ann-httpexchange-composed]]
|
||||
== Custom Annotations
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-composed[See equivalent in the Servlet stack]#
|
||||
|
||||
`@HttpExchange` annotated controllers support the use of xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[composed annotations]
|
||||
for request mapping. Those are annotations that are themselves meta-annotated
|
||||
with `@HttpExchange` and composed to redeclare a subset (or all) of the
|
||||
`@HttpExchange` attributes with a narrower, more specific purpose.
|
||||
|
||||
`@GetExchange`, `@PostExchange`, `@PutExchange`, `@DeleteExchange`,
|
||||
and `@PatcExchange` are examples of composed annotations. They are provided
|
||||
because, arguably, most controller methods should be mapped to a specific
|
||||
HTTP method versus using `@HttpExchange`, which, by default,
|
||||
matches to all HTTP methods. If you need an example of composed annotations,
|
||||
look at how those are declared.
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-methods.adoc[See equivalent in the Servlet stack]#
|
||||
|
||||
`@RequestMapping` and `@HttpExchange` handler methods have a flexible signature and can choose from a range of
|
||||
`@RequestMapping` handler methods have a flexible signature and can choose from a range of
|
||||
supported controller method arguments and return values.
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
[[webflux-ann-requestmapping]]
|
||||
= Request Mapping
|
||||
= Mapping Requests
|
||||
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[See equivalent in the Servlet stack]#
|
||||
|
||||
This section discusses request mapping for annotated controllers.
|
||||
|
||||
[[webflux-ann-requestmapping-annotation]]
|
||||
== `@RequestMapping`
|
||||
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-annotation[See equivalent in the Servlet stack]#
|
||||
|
||||
The `@RequestMapping` annotation is used to map requests to controllers methods. It has
|
||||
various attributes to match by URL, HTTP method, request parameters, headers, and media
|
||||
types. You can use it at the class level to express shared mappings or at the method level
|
||||
|
@ -500,3 +507,68 @@ Kotlin::
|
|||
|
||||
|
||||
|
||||
[[webflux-ann-httpexchange-annotation]]
|
||||
== `@HttpExchange`
|
||||
[.small]#xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-httpexchange-annotation[See equivalent in the Reactive stack]#
|
||||
|
||||
As an alternative to `@RequestMapping`, you can also handle requests with `@HttpExchange`
|
||||
methods. Such methods are declared on an
|
||||
xref:integration/rest-clients.adoc#rest-http-interface[HTTP Interface] and can be used as
|
||||
a client via `HttpServiceProxyFactory` or implemented by a server `@Controller`.
|
||||
|
||||
For example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
public Person getPerson(@PathVariable Long id) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public void add(@RequestBody Person person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
fun getPerson(@PathVariable id: Long): Person {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun add(@RequestBody person: Person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
There some differences between `@HttpExchange` and `@RequestMapping` since the
|
||||
former needs to remain suitable for client and server use. For example, while
|
||||
`@RequestMapping` can be declared to handle any number of paths and each path can
|
||||
be a pattern, `@HttpExchange` must be declared with a single, concrete path. There are
|
||||
also differences in the supported method parameters. Generally, `@HttpExchange` supports
|
||||
a subset of method parameters that `@RequestMapping` does, excluding any parameters that
|
||||
are server side only. For details see the list of supported method parameters for
|
||||
xref:integration/rest-clients.adoc#rest-http-interface-method-parameters[HTTP interface] and for
|
||||
xref:web/webflux/controller/ann-methods/arguments.adoc[@RequestMapping].
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
[[mvc-ann-httpexchange]]
|
||||
= HttpExchange
|
||||
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc[
|
||||
See equivalent in the Reactive stack]#
|
||||
|
||||
Similarly to
|
||||
xref:web/webmvc/mvc-controller/ann-requestmapping.adoc[`@RequestMapping`],
|
||||
you can use the `@HttpExchange` annotation to map requests to controllers
|
||||
methods. However, while `@RequestMapping` is only supported on the server side, `@HttpExchange` can be used both to create a server-side mapping and
|
||||
xref:integration/rest-clients.adoc#rest-http-interface[an HTTP
|
||||
Interface Client] that allows making requests.
|
||||
|
||||
`@HttpExchange` has various attributes to match by URL, HTTP method, and media
|
||||
types. You can use it at the class level to express shared mappings or at the
|
||||
method level to narrow down to a specific endpoint mapping.
|
||||
|
||||
There are also HTTP method specific shortcut variants of `@HttpExchange`:
|
||||
|
||||
* `@GetExchange`
|
||||
* `@PostExchange`
|
||||
* `@PutExchange`
|
||||
* `@DeleteExchange`
|
||||
* `@PatchExchange`
|
||||
|
||||
The shortcuts are xref:web/webmvc/mvc-controller/ann-httpexchange.adoc#mvc-ann-httpexchange-composed[Custom Annotations] that are provided
|
||||
because, arguably, most controller methods should be mapped to a specific
|
||||
HTTP method versus using `@HttpExchange`, which, by default, matches
|
||||
to all HTTP methods.
|
||||
An `@HttpExchange` is still needed at the class level to express shared mappings.
|
||||
|
||||
The following example has type and method level mappings:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
public Person getPerson(@PathVariable Long id) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public void add(@RequestBody Person person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
fun getPerson(@PathVariable id: Long): Person {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun add(@RequestBody person: Person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
`@HttpExhange` supports a very similar method signature to `@MessageMapping`,
|
||||
however, since it needs to be suitable both for requester and responder use,
|
||||
there are slight differences, which are discussed below.
|
||||
|
||||
[[mvc-ann-httpexchange-uri-templates]]
|
||||
== URI patterns
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-uri-templates[See equivalent in the Reactive stack]#
|
||||
|
||||
URI patterns resolution support is very similar to the one offered by xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-uri-templates[`@RequestMapping`], with the difference
|
||||
that while `@RequestMapping` accepts a `String` array as its `value` or `path`
|
||||
parameter that is used to specify the URI patterns, only a single `String` can be passed
|
||||
as the `value` of `@HttpExchange`.
|
||||
|
||||
[[mvc-ann-httpexchange-contenttype]]
|
||||
== Consumable Media Types
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-contenttype[See equivalent in the Reactive stack]#
|
||||
|
||||
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"]
|
||||
----
|
||||
@PostExchange(path = "/pets", contentType = "application/json") // <1>
|
||||
public void addPet(@RequestBody Pet pet) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using a `contentType` attribute to narrow the mapping by the content type.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@PostExchange("/pets", contentType = "application/json") // <1>
|
||||
fun addPet(@RequestBody pet: Pet) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using a `contentType` attribute to narrow the mapping by the content type.
|
||||
======
|
||||
|
||||
The `contentType` attribute accepts a single `String` as the attribute value.
|
||||
|
||||
You can also declare a shared `contentType` attribute at the class level.
|
||||
Unlike most other request-mapping attributes, however, when used at the
|
||||
class level, a method-level `contentType` attribute overrides rather than
|
||||
extends the class-level declaration.
|
||||
|
||||
TIP: `MediaType` provides constants for commonly used media types, such as
|
||||
`APPLICATION_JSON_VALUE` and `APPLICATION_XML_VALUE`.
|
||||
|
||||
|
||||
[[mvc-ann-httpexchange-accept]]
|
||||
== Producible Media Types
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-accept[See equivalent in the Reactive stack]#
|
||||
|
||||
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"]
|
||||
----
|
||||
@GetExchange(path = "/pets/{petId}", accept = "application/json") // <1>
|
||||
@ResponseBody
|
||||
public Pet getPet(@PathVariable String petId) {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using an `accept` attribute to narrow the mapping by the content type that
|
||||
can be served.
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@GetExchange("/pets/{petId}", accept = ["application/json"]) // <1>
|
||||
@ResponseBody
|
||||
fun getPet(@PathVariable petId: String): Pet {
|
||||
// ...
|
||||
}
|
||||
----
|
||||
<1> Using an `accept` attribute to narrow the mapping by the content type that
|
||||
can be served.
|
||||
======
|
||||
|
||||
The `accept` attribute accepts a `String` array as the attribute value.
|
||||
|
||||
You can declare a shared `accept` attribute at the class level. Unlike most
|
||||
other request-mapping attributes, however, when used at the class level,
|
||||
a method-level `accept` attribute
|
||||
overrides rather than extends the class-level declaration.
|
||||
|
||||
TIP: `MediaType` provides constants for commonly used media types, such as
|
||||
`APPLICATION_JSON_VALUE` and `APPLICATION_XML_VALUE`.
|
||||
|
||||
|
||||
[[mvc-ann-httpexchange-params-and-headers]]
|
||||
== Parameters, headers
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-params-and-headers[See equivalent in the Reactive stack]#
|
||||
|
||||
You can narrow request mappings based on request parameter and headers
|
||||
conditions. It is supported for `@HttpExchange` in the same way as in xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-params-and-headers[`@RequestMapping` parameter and header support] .
|
||||
|
||||
|
||||
[[mvc-ann-httpexchange-head-options]]
|
||||
== HTTP HEAD, OPTIONS
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-head-options[See equivalent in the Reactive stack]#
|
||||
|
||||
The support of `HTTP HEAD` and `HTTP OPTIONS` in `@HttpExchange` annotated
|
||||
controllers is the same xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-head-options[
|
||||
as in `@RequestMapping` annotated controllers].
|
||||
|
||||
[[mvc-ann-httpexchange-composed]]
|
||||
== Custom Annotations
|
||||
[.small]#xref:web/webflux/controller/ann-httpexchange.adoc#webflux-ann-httpexchange-head-options[See equivalent in the Reactive stack]#
|
||||
|
||||
`@HttpExchange` annotated controllers support the use of xref:core/beans/classpath-scanning.adoc#beans-meta-annotations[composed annotations]
|
||||
for request mapping. Those are annotations that are themselves meta-annotated
|
||||
with `@HttpExchange` and composed to redeclare a subset (or all) of the
|
||||
`@HttpExchange` attributes with a narrower, more specific purpose.
|
||||
|
||||
`@GetExchange`, `@PostExchange`, `@PutExchange`, `@DeleteExchange`,
|
||||
and `@PatcExchange` are examples of composed annotations. They are provided
|
||||
because, arguably, most controller methods should be mapped to a specific
|
||||
HTTP method versus using `@HttpExchange`, which, by default,
|
||||
matches to all HTTP methods. If you need an example of composed annotations,
|
||||
look at how those are declared.
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
[.small]#xref:web/webflux/controller/ann-methods.adoc[See equivalent in the Reactive stack]#
|
||||
|
||||
`@RequestMapping` and `@HttpExchange` handler methods have a flexible signature and can choose from a range of
|
||||
`@RequestMapping` handler methods have a flexible signature and can choose from a range of
|
||||
supported controller method arguments and return values.
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
[[mvc-ann-requestmapping]]
|
||||
= Request Mapping
|
||||
= Mapping Requests
|
||||
|
||||
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc[See equivalent in the Reactive stack]#
|
||||
|
||||
This section discusses request mapping for annotated controllers.
|
||||
|
||||
|
||||
|
||||
[[mvc-ann-requestmapping-annotation]]
|
||||
== `@RequestMapping`
|
||||
|
||||
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-requestmapping-annotation[See equivalent in the Reactive stack]#
|
||||
|
||||
You can use the `@RequestMapping` annotation to map requests to controllers methods. It has
|
||||
various attributes to match by URL, HTTP method, request parameters, headers, and media
|
||||
types. You can use it at the class level to express shared mappings or at the method level
|
||||
|
@ -549,3 +558,68 @@ Kotlin::
|
|||
|
||||
|
||||
|
||||
[[mvc-ann-httpexchange-annotation]]
|
||||
== `@HttpExchange`
|
||||
[.small]#xref:web/webflux/controller/ann-requestmapping.adoc#webflux-ann-httpexchange-annotation[See equivalent in the Reactive stack]#
|
||||
|
||||
As an alternative to `@RequestMapping`, you can also handle requests with `@HttpExchange`
|
||||
methods. Such methods are declared on an
|
||||
xref:integration/rest-clients.adoc#rest-http-interface[HTTP Interface] and can be used as
|
||||
a client via `HttpServiceProxyFactory` or implemented by a server `@Controller`.
|
||||
|
||||
For example:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
public Person getPerson(@PathVariable Long id) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public void add(@RequestBody Person person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@RestController
|
||||
@HttpExchange("/persons")
|
||||
class PersonController {
|
||||
|
||||
@GetExchange("/{id}")
|
||||
fun getPerson(@PathVariable id: Long): Person {
|
||||
// ...
|
||||
}
|
||||
|
||||
@PostExchange
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
fun add(@RequestBody person: Person) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
There some differences between `@HttpExchange` and `@RequestMapping` since the
|
||||
former needs to remain suitable for client and server use. For example, while
|
||||
`@RequestMapping` can be declared to handle any number of paths and each path can
|
||||
be a pattern, `@HttpExchange` must be declared with a single, concrete path. There are
|
||||
also differences in the supported method parameters. Generally, `@HttpExchange` supports
|
||||
a subset of method parameters that `@RequestMapping` does, excluding any parameters that
|
||||
are server side only. For details see the list of supported method parameters for
|
||||
xref:integration/rest-clients.adoc#rest-http-interface-method-parameters[HTTP interface] and for
|
||||
xref:web/webmvc/mvc-controller/ann-methods/arguments.adoc[@RequestMapping].
|
||||
|
|
Loading…
Reference in New Issue