REST Endpoints
The Spring Framework provides two choices for making calls to REST endpoints:
-
rest-resttemplate: The original Spring REST client with a synchronous, template method API.
-
WebClient: a non-blocking, reactive alternative that supports both synchronous and asynchronous as well as streaming scenarios.
As of 5.0, the non-blocking, reactive WebClient offers a modern alternative to the
RestTemplate with efficient support for both synchronous and asynchronous as well as streaming
scenarios. The RestTemplate will be deprecated in a future version and will not have
major new features added going forward.
|
RestTemplate
The RestTemplate
provides a higher level API over HTTP client libraries. It makes it
easy to invoke REST endpoints in a single line. It exposes the following groups of
overloaded methods:
Method group | Description |
---|---|
|
Retrieves a representation via GET. |
|
Retrieves a |
|
Retrieves all headers for a resource by using HEAD. |
|
Creates a new resource by using POST and returns the |
|
Creates a new resource by using POST and returns the representation from the response. |
|
Creates a new resource by using POST and returns the representation from the response. |
|
Creates or updates a resource by using PUT. |
|
Updates a resource by using PATCH and returns the representation from the response.
Note that the JDK |
|
Deletes the resources at the specified URI by using DELETE. |
|
Retrieves allowed HTTP methods for a resource by using ALLOW. |
|
More generalized (and less opinionated) version of the preceding methods that provides extra
flexibility when needed. It accepts a These methods allow the use of |
|
The most generalized way to perform a request, with full control over request preparation and response extraction through callback interfaces. |
Initialization
The default constructor uses java.net.HttpURLConnection
to perform requests. You can
switch to a different HTTP library with an implementation of ClientHttpRequestFactory
.
There is built-in support for the following:
-
Apache HttpComponents
-
Netty
-
OkHttp
For example, to switch to Apache HttpComponents, you can use the following:
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
Each ClientHttpRequestFactory
exposes configuration options specific to the underlying
HTTP client library — for example, for credentials, connection pooling, and other details.
Note that the java.net implementation for HTTP requests can raise an exception when
accessing the status of a response that represents an error (such as 401). If this is an
issue, switch to another HTTP client library.
|
URIs
Many of the RestTemplate
methods accept a URI template and URI template variables,
either as a String
variable argument, or as Map<String,String>
.
The following example uses a String
variable argument:
String result = restTemplate.getForObject(
"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
The following example uses a Map<String, String>
:
Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject(
"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
Keep in mind URI templates are automatically encoded, as the following example shows:
restTemplate.getForObject("https://example.com/hotel list", String.class);
// Results in request to "https://example.com/hotel%20list"
You can use the uriTemplateHandler
property of RestTemplate
to customize how URIs
are encoded. Alternatively, you can prepare a java.net.URI
and pass it into one of
the RestTemplate
methods that accepts a URI
.
For more details on working with and encoding URIs, see URI Links.
Headers
You can use the exchange()
methods to specify request headers, as the following example shows:
String uriTemplate = "https://example.com/hotels/{hotel}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);
RequestEntity<Void> requestEntity = RequestEntity.get(uri)
.header(("MyRequestHeader", "MyValue")
.build();
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();
You can obtain response headers through many RestTemplate
method variants that return
ResponseEntity
.
Body
Objects passed into and returned from RestTemplate
methods are converted to and from raw
content with the help of an HttpMessageConverter
.
On a POST, an input object is serialized to the request body, as the following example shows:
URI location = template.postForLocation("https://example.com/people", person);
You need not explicitly set the Content-Type header of the request. In most cases,
you can find a compatible message converter based on the source Object
type, and the chosen
message converter sets the content type accordingly. If necessary, you can use the
exchange
methods to explicitly provide the Content-Type
request header, and that, in
turn, influences what message converter is selected.
On a GET, the body of the response is deserialized to an output Object
, as the following example shows:
Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);
The Accept
header of the request does not need to be explicitly set. In most cases,
a compatible message converter can be found based on the expected response type, which
then helps to populate the Accept
header. If necessary, you can use the exchange
methods to provide the Accept
header explicitly.
By default, RestTemplate
registers all built-in
message converters, depending on classpath checks that help
to determine what optional conversion libraries are present. You can also set the message
converters to use explicitly.
Message Conversion
The spring-web
module contains the HttpMessageConverter
contract for reading and
writing the body of HTTP requests and responses through InputStream
and OutputStream
.
HttpMessageConverter
instances are used on the client side (for example, in the RestTemplate
) and
on the server side (for example, in Spring MVC REST controllers).
Concrete implementations for the main media (MIME) types are provided in the framework
and are, by default, registered with the RestTemplate
on the client side and with
RequestMethodHandlerAdapter
on the server side (see
Configuring Message Converters).
The implementations of HttpMessageConverter
are described in the following sections.
For all converters, a default media type is used, but you can override it by setting the
supportedMediaTypes
bean property. The following table describes each implementation:
MessageConverter | Description |
---|---|
|
An |
|
An |
|
An |
|
An |
|
An |
|
An |
|
An |
|
An |
Jackson JSON Views
You can specify a Jackson JSON View to serialize only a subset of the object properties, as the following example shows:
MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);
RequestEntity<MappingJacksonValue> requestEntity =
RequestEntity.post(new URI("https://example.com/user")).body(value);
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
Multipart
To send multipart data, you need to provide a MultiValueMap<String, Object>
whose values
may be an Object
for part content, a Resource
for a file part, or an HttpEntity
for
part content with headers. For example:
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("fieldPart", "fieldValue");
parts.add("filePart", new FileSystemResource("...logo.png"));
parts.add("jsonPart", new Person("Jason"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
parts.add("xmlPart", new HttpEntity<>(myBean, headers));
In most cases, you do not have to specify the Content-Type
for each part. The content
type is determined automatically based on the HttpMessageConverter
chosen to serialize
it or, in the case of a Resource
based on the file extension. If necessary, you can
explicitly provide the MediaType
with an HttpEntity
wrapper.
Once the MultiValueMap
is ready, you can pass it to the RestTemplate
, as show below:
MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);
If the MultiValueMap
contains at least one non-String
value, the Content-Type
is set
to multipart/form-data
by the FormHttpMessageConverter
. If the MultiValueMap
has
String
values the Content-Type
is defaulted to application/x-www-form-urlencoded
.
If necessary the Content-Type
may also be set explicitly.
Using AsyncRestTemplate
(Deprecated)
The AsyncRestTemplate
is deprecated. For all use cases where you might consider using
AsyncRestTemplate
, use the WebClient instead.