Browse Source

Revise docs for server use of `@HttpExchange`

Closes gh-30980
pull/31006/head
rstoyanchev 2 years ago
parent
commit
5115684baf
  1. 28
      framework-docs/modules/ROOT/pages/integration/rest-clients.adoc
  2. 2
      framework-docs/modules/ROOT/pages/rsocket.adoc
  3. 215
      framework-docs/modules/ROOT/pages/web/webflux/controller/ann-httpexchange.adoc
  4. 2
      framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods.adoc
  5. 74
      framework-docs/modules/ROOT/pages/web/webflux/controller/ann-requestmapping.adoc
  6. 215
      framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-httpexchange.adoc
  7. 2
      framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods.adoc
  8. 76
      framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-requestmapping.adoc

28
framework-docs/modules/ROOT/pages/integration/rest-clients.adoc

@ -363,12 +363,13 @@ If necessary the `Content-Type` may also be set explicitly. @@ -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,30 +383,31 @@ One, declare an interface with `@HttpExchange` methods: @@ -382,30 +383,31 @@ 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.
For `RestClient`:
[source,java,indent=0,subs="verbatim,quotes"]
----
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
WebClientAdapter adapter = WebClientAdapter.forClient(webClient)
RestClient restClient = RestClient.builder().baseUrl("https://api.github.com/").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
RepositoryService service = factory.createClient(RepositoryService.class);
----
using `RestClient`:
For `WebClient`:
[source,java,indent=0,subs="verbatim,quotes"]
----
RestClient restClient = RestClient.builder().baseUrl("https://api.github.com/").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
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);
----
or using `RestTemplate`:
For `RestTemplate`:
[source,java,indent=0,subs="verbatim,quotes"]
----

2
framework-docs/modules/ROOT/pages/rsocket.adoc

@ -871,7 +871,7 @@ interaction type(s): @@ -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:

215
framework-docs/modules/ROOT/pages/web/webflux/controller/ann-httpexchange.adoc

@ -1,215 +0,0 @@ @@ -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.

2
framework-docs/modules/ROOT/pages/web/webflux/controller/ann-methods.adoc

@ -4,7 +4,7 @@ @@ -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.

74
framework-docs/modules/ROOT/pages/web/webflux/controller/ann-requestmapping.adoc

@ -1,8 +1,15 @@ @@ -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:: @@ -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].

215
framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-httpexchange.adoc

@ -1,215 +0,0 @@ @@ -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.

2
framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-methods.adoc

@ -4,7 +4,7 @@ @@ -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.

76
framework-docs/modules/ROOT/pages/web/webmvc/mvc-controller/ann-requestmapping.adoc

@ -1,8 +1,17 @@ @@ -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:: @@ -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…
Cancel
Save