-
Notifications
You must be signed in to change notification settings - Fork 38.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support @HttpExchange for server-side handling
See gh-30980
- Loading branch information
1 parent
646fd3e
commit d1d5b54
Showing
8 changed files
with
668 additions
and
11 deletions.
There are no files selected for viewing
215 changes: 215 additions & 0 deletions
215
framework-docs/modules/ROOT/pages/web/webflux/controller/ann-httpexchange.adoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
[[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. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.