SpringRestTemplate学习笔记,参考官方文档
28.10 Accessing RESTful services on the client
28.10在客户端上访问RESTful服务
The RestTemplate
is the core class for client-side access to RESTful services. It is conceptually similar to other template classes in Spring, such as JdbcTemplate
and JmsTemplate
and other template classes found in other Spring portfolio projects. RestTemplate’s behavior is customized by providing callback methods and configuring the `HttpMessageConverter
used to marshal objects into the HTTP request body and to unmarshal any response back into an object. As it is common to use XML as a message format, Spring provides a MarshallingHttpMessageConverter
that uses the Object-to-XML framework that is part of the org.springframework.oxm
package. This gives you a wide range of choices of XML to Object mapping technologies to choose from.
RestTemplate是客户端访问RESTful服务的核心类。 从概念上讲,它类似于Spring中的其他模板类,例如JdbcTemplate和JmsTemplate以及其他Spring产品组合项目中的其他模板类。 RestTemplate的行为是通过提供回调方法和配置用于将对象封送至HTTP请求主体并将所有响应封送回对象的HttpMessageConverter进行自定义的。 由于通常将XML用作消息格式,因此Spring提供了一个MarshallingHttpMessageConverter,该对象使用org.springframework.oxm包中的Object-to-XML框架。 这为您提供了多种XML到对象映射技术的选择。
This section describes how to use the RestTemplate
and its associated HttpMessageConverters
.
本节介绍如何使用RestTemplate及其关联的HttpMessageConverters。
28.10.1 RestTemplate
Invoking RESTful services in Java is typically done using a helper class such as Apache HttpComponents HttpClient
. For common REST operations this approach is too low level as shown below.
用Java调用RESTful服务通常是使用诸如Apache HttpComponents HttpClient之类的帮助类来完成的。 对于常见的REST操作,此方法级别太低,如下所示。
String uri = "http://example.com/hotels/1/bookings";
PostMethod post = new PostMethod(uri);
String request = // create booking request content
post.setRequestEntity(new StringRequestEntity(request));
httpClient.executeMethod(post);
if (HttpStatus.SC_CREATED == post.getStatusCode()) {
Header location = post.getRequestHeader("Location");
if (location != null) {
System.out.println("Created new booking at :" + location.getValue());
}
}
RestTemplate provides higher level methods that correspond to each of the six main HTTP methods that make invoking many RESTful services a one-liner and enforce REST best practices.
RestTemplate提供了与六个主要HTTP方法中的每个方法相对应的高级方法,这使调用许多RESTful服务成为一种行为并强制执行REST最佳实践。
Table 28.1. Overview of RestTemplate methods
HTTP Method | RestTemplate Method |
---|---|
DELETE | |
GET | |
HEAD | |
OPTIONS | |
POST | postForLocation(String url, Object request, String… uriVariables) postForObject(String url, Object request, Class<T> responseType, String… uriVariables) |
PUT | |
PATCH and others |
The names of RestTemplate methods follow a naming convention, the first part indicates what HTTP method is being invoked and the second part indicates what is returned. For example, the method getForObject() will perform a GET, convert the HTTP response into an object type of your choice and return that object. The method postForLocation() will do a POST, converting the given object into a HTTP request and return the response HTTP Location header where the newly created object can be found. In case of an exception processing the HTTP request, an exception of the type RestClientException will be thrown; this behavior can be changed by plugging in another ResponseErrorHandler implementation into the RestTemplate.
RestTemplate方法的名称遵循命名约定,第一部分指示正在调用的HTTP方法,第二部分指示返回的内容。 例如,方法getForObject()将执行GET,将HTTP响应转换为您选择的对象类型,然后返回该对象。 方法postForLocation()将执行POST,将给定对象转换为HTTP请求并返回响应HTTP Location标头,在该标头中可以找到新创建的对象。 在处理HTTP请求的异常情况下,将抛出RestClientException类型的异常。 可以通过将另一个ResponseErrorHandler实现插入RestTemplate来更改此行为。
The exchange
and execute
methods are generalized versions of the more specific methods listed above them and can support additional combinations and methods, e.g. HTTP PATCH. However, note that the underlying HTTP library must also support the desired combination. The JDK HttpURLConnection
does not support the PATCH
method but Apache HttpComponents HttpClient version 4.2 or later does. They also enable RestTemplate
to read an HTTP response to a generic type (e.g. List<Account>
), using a ParameterizedTypeReference
, a new class that enables capturing and passing generic type info.
交换和执行方法是它们上方列出的更具体方法的通用版本,可以支持其他组合和方法,例如: HTTP修补程序。 但是,请注意,基础HTTP库也必须支持所需的组合。 JDK HttpURLConnection不支持PATCH方法,但是Apache HttpComponents HttpClient版本4.2或更高版本支持。 它们还使RestTemplate可以使用ParameterizedTypeReference读取对通用类型(例如List <Account>)的HTTP响应,ParameterizedTypeReference是一个新类,可以捕获和传递通用类型信息。
Objects passed to and returned from these methods are converted to and from HTTP messages by HttpMessageConverter
implementations. Converters for the main MIME types are registered by default, but you can also override the defaults and register custom converters via the messageConverters()
bean property. The default converters are ByteArrayHttpMessageConverter
, StringHttpMessageConverter
, ResourceHttpMessageConverter
, SourceHttpMessageConverter
as well as AllEncompassingFormHttpMessageConverter
and a few provider-specific converters: e.g. MappingJackson2HttpMessageConverter
when Jackson is present on the classpath.
通过HttpMessageConverter实现,可以将传递给这些方法和从这些方法返回的对象与HTTP消息进行相互转换。 默认情况下会注册主要MIME类型的转换器,但是您也可以覆盖默认值,并通过messageConverters()bean属性注册自定义转换器。 默认的转换器是ByteArrayHttpMessageConverter,StringHttpMessageConverter,ResourceHttpMessageConverter,SourceHttpMessageConverter以及AllEncompassingFormHttpMessageConverter和一些提供程序特定的转换器:例如 类路径上存在Jackson时,MappingpingJackson2HttpMessageConverter。
Each method takes URI template arguments in two forms, either as a String
variable-length argument or a Map<String,String>
. For example,
每个方法都采用两种形式的URI模板参数,即String可变长度参数或Map <String,String>。 例如,
String result = restTemplate.getForObject(
"http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21");
using variable-length arguments and
使用动态个数参数
Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject(
"http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
using a Map<String,String>
.
To create an instance of RestTemplate
you can simply call the default no-arg constructor. This will use standard Java classes from the java.net
package as the underlying implementation to create HTTP requests. This can be overridden by specifying an implementation of ClientHttpRequestFactory
. Spring provides the implementation HttpComponentsClientHttpRequestFactory
that uses the Apache HttpComponents HttpClient
to create requests. HttpComponentsClientHttpRequestFactory
is configured using an instance of org.apache.http.client.HttpClient
which can in turn be configured with credentials information or connection pooling functionality.
使用Map <String,String>。
要创建RestTemplate的实例,您可以简单地调用默认的no-arg构造函数。 这将使用java.net包中的标准Java类作为基础实现来创建HTTP请求。 可以通过指定ClientHttpRequestFactory的实现来覆盖它。 Spring提供了HttpComponentsClientHttpRequestFactory实现,该实现使用Apache HttpComponents HttpClient创建请求。 HttpComponentsClientHttpRequestFactory使用org.apache.http.client.HttpClient实例进行配置,而该实例又可以使用凭据信息或连接池功能进行配置。
Note that the java.net
implementation for HTTP requests may raise an exception when accessing the status of a response that represents an error (e.g. 401). If this is an issue, switch to HttpComponentsClientHttpRequestFactory
instead.
请注意,访问代表错误的响应状态(例如401)时,HTTP请求的java.net实现可能会引发异常。 如果这是一个问题,请改用HttpComponentsClientHttpRequestFactory。
The previous example using Apache HttpComponents HttpClient
directly rewritten to use the RestTemplate
is shown below
上面的示例使用Apache HttpComponents HttpClient直接重写以使用RestTemplate,如下所示
uri = "http://example.com/hotels/{id}/bookings";
RestTemplate template = new RestTemplate();
Booking booking = // create booking object
URI location = template.postForLocation(uri, booking, "1");
To use Apache HttpComponents instead of the native java.net
functionality, construct the RestTemplate
as follows:
要使用Apache HttpComponents代替本机java.net功能,请按以下方式构造RestTemplate:
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
Apache HttpClient supports gzip encoding. To use it, construct a HttpComponentsClientHttpRequestFactory
like so:
Apache HttpClient支持gzip编码。 要使用它,像这样构造一个HttpComponentsClientHttpRequestFactory:
HttpClient httpClient = HttpClientBuilder.create().build();
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
RestTemplate restTemplate = new RestTemplate(requestFactory);
The general callback interface is RequestCallback
and is called when the execute method is invoked.
通用的回调接口是RequestCallback,在调用execute方法时将调用该接口。
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, String... uriVariables)
// also has an overload with uriVariables as a Map<String, String>.
The RequestCallback
interface is defined as
RequestCallback接口定义为
public interface RequestCallback {
void doWithRequest(ClientHttpRequest request) throws IOException;
}
and allows you to manipulate the request headers and write to the request body. When using the execute method you do not have to worry about any resource management, the template will always close the request and handle any errors. Refer to the API documentation for more information on using the execute method and the meaning of its other method arguments.
并允许您处理请求标头并写入请求正文。 使用execute方法时,您不必担心任何资源管理,模板将始终关闭请求并处理任何错误。 有关使用execute方法及其其他方法参数的含义的更多信息,请参阅API文档。
Working with the URI
For each of the main HTTP methods, the RestTemplate
provides variants that either take a String URI or java.net.URI
as the first argument.
使用URI
对于每个主要的HTTP方法,RestTemplate提供的变体都将String URI或java.net.URI作为第一个参数。
The String URI variants accept template arguments as a String variable-length argument or as a Map<String,String>
. They also assume the URL String is not encoded and needs to be encoded. For example the following:
String URI变体接受模板参数作为String可变长度参数或Map <String,String>。 他们还假定URL字符串未编码,需要进行编码。 例如以下内容:
restTemplate.getForObject("http://example.com/hotel list", String.class);
will perform a GET on http://example.com/hotel%20list
. That means if the input URL String is already encoded, it will be encoded twice — i.e. http://example.com/hotel%20list
will become http://example.com/hotel%2520list
. If this is not the intended effect, use the java.net.URI
method variant, which assumes the URL is already encoded is also generally useful if you want to reuse a single (fully expanded) URI
multiple times.
The UriComponentsBuilder
class can be used to build and encode the URI
including support for URI templates. For example you can start with a URL String:
将在http://example.com/hotel%20list上执行GET。 这意味着,如果输入的URL字符串已被编码,它将被编码两次。-,即http://example.com/hotel%20list将变为http://example.com/hotel%2520list。 如果这不是预期的效果,请使用java.net.URI方法变体,该变体假定URL已经被编码,如果要多次重用单个(完全扩展的)URI,通常也很有用。
UriComponentsBuilder类可用于构建和编码URI,包括对URI模板的支持。 例如,您可以以URL字符串开头:
UriComponents uriComponents = UriComponentsBuilder.fromUriString(
"http://example.com/hotels/{hotel}/bookings/{booking}").build()
.expand("42", "21")
.encode();
URI uri = uriComponents.toUri();
Or specify each URI component individually: 或分别指定每个URI组件:
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()
.expand("42", "21")
.encode();
URI uri = uriComponents.toUri();
Dealing with request and response headers
处理请求和响应头
Besides the methods described above, the RestTemplate
also has the exchange()
method, which can be used for arbitrary HTTP method execution based on the HttpEntity
class.
除了上述方法外,RestTemplate还具有exchange()方法,该方法可用于基于HttpEntity类的任意HTTP方法执行。
Perhaps most importantly, the exchange()
method can be used to add request headers and read response headers. For example:
也许最重要的是,可以使用exchange()方法添加请求标头和读取响应标头。 例如:
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyRequestHeader", "MyValue");
HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
HttpEntity<String> response = template.exchange(
"http://example.com/hotels/{hotel}",
HttpMethod.GET, requestEntity, String.class, "42");
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();
In the above example, we first prepare a request entity that contains the MyRequestHeader
header. We then retrieve the response, and read the MyResponseHeader
and body.
在上面的示例中,我们首先准备一个包含MyRequestHeader标头的请求实体。 然后,我们检索响应,并读取MyResponseHeader和正文。
Jackson JSON Views support
Jackson JSON视图支持
It is possible to specify a Jackson JSON View to serialize only a subset of the object properties. For example:
可以指定Jackson JSON视图以仅序列化对象属性的子集。 例如:
MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);
HttpEntity<MappingJacksonValue> entity = new HttpEntity<MappingJacksonValue>(value);
String s = template.postForObject("http://example.com/user", entity, String.class);
28.10.2 HTTP message conversion
28.10.2 HTTP消息转换
Objects passed to and returned from the methods getForObject()
, postForLocation()
, and put()
are converted to HTTP requests and from HTTP responses by HttpMessageConverters
. The HttpMessageConverter
interface is shown below to give you a better feel for its functionality
传递给方法getForObject(),postForLocation()和put()以及从方法返回的对象由HttpMessageConverters转换为HTTP请求,并从HTTP响应转换为HTTP请求。 如下所示,HttpMessageConverter接口使您可以更好地了解其功能
public interface HttpMessageConverter<T> {
// Indicate whether the given class and media type can be read by this converter.
boolean canRead(Class<?> clazz, MediaType mediaType);
// Indicate whether the given class and media type can be written by this converter.
boolean canWrite(Class<?> clazz, MediaType mediaType);
// Return the list of MediaType objects supported by this converter.
List<MediaType> getSupportedMediaTypes();
// Read an object of the given type from the given input message, and returns it.
T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
// Write an given object to the given output message.
void write(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;
}
Concrete implementations for the main media (mime) types are provided in the framework and are registered by default with the RestTemplate
on the client-side and with RequestMethodHandlerAdapter
on the server-side.
框架中提供了主要媒体(mime)类型的具体实现,默认情况下,它们在客户端的RestTemplate和服务器端的RequestMethodHandlerAdapter中注册。
The implementations of HttpMessageConverter
s are described in the following sections. For all converters a default media type is used but can be overridden by setting the supportedMediaTypes
bean property
以下各节介绍了HttpMessageConverters的实现。 对于所有转换器,都使用默认媒体类型,但可以通过设置supportedMediaTypes bean属性来覆盖它
StringHttpMessageConverter
An HttpMessageConverter
implementation that can read and write Strings from the HTTP request and response. By default, this converter supports all text media types ( text/*
), and writes with a Content-Type
of text/plain
.
StringHttpMessageConverter
HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入字符串。默认情况下,此转换器支持所有文本媒体类型(text / *),并使用文本/纯文本的Content-Type进行写入。
FormHttpMessageConverter
An HttpMessageConverter
implementation that can read and write form data from the HTTP request and response. By default, this converter reads and writes the media type application/x-www-form-urlencoded
. Form data is read from and written into a MultiValueMap<String, String>
.
FormHttpMessageConverter
HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入表单数据。默认情况下,此转换器读取和写入媒体类型application / x-www-form-urlencoded。从MultiValueMap <String,String>中读取并写入表单数据。
ByteArrayHttpMessageConverter
An HttpMessageConverter
implementation that can read and write byte arrays from the HTTP request and response. By default, this converter supports all media types ( */*
), and writes with a Content-Type
of application/octet-stream
. This can be overridden by setting the supportedMediaTypes
property, and overriding getContentType(byte[])
.
MarshallingHttpMessageConverter
An HttpMessageConverter
implementation that can read and write XML using Spring’s Marshaller
and Unmarshaller
abstractions from the org.springframework.oxm
package. This converter requires a Marshaller
and Unmarshaller
before it can be used. These can be injected via constructor or bean properties. By default this converter supports ( text/xml
) and ( application/xml
).
封送处理HttpMessageConverter
HttpMessageConverter实现,可以使用org.springframework.oxm包中Spring的Marshaller和Unmarshaller抽象来读写XML。该转换器需要使用Marshaller和Unmarshaller才能使用。这些可以通过构造函数或bean属性注入。默认情况下,此转换器支持(text / xml)和(application / xml)。
MappingJackson2HttpMessageConverter
An HttpMessageConverter
implementation that can read and write JSON using Jackson’s ObjectMapper
. JSON mapping can be customized as needed through the use of Jackson’s provided annotations. When further control is needed, a custom ObjectMapper
can be injected through the ObjectMapper
property for cases where custom JSON serializers/deserializers need to be provided for specific types. By default this converter supports ( application/json
).
MappingJackson2HttpMessageConverter
HttpMessageConverter实现,可以使用Jackson的ObjectMapper读写JSON。可以根据需要通过使用Jackson提供的注释来自定义JSON映射。当需要进一步控制时,对于需要为特定类型提供自定义JSON序列化器/反序列化器的情况,可以通过ObjectMapper属性注入自定义ObjectMapper。默认情况下,此转换器支持(application / json)。
MappingJackson2XmlHttpMessageConverter
An HttpMessageConverter
implementation that can read and write XML using Jackson XML extension’s XmlMapper
. XML mapping can be customized as needed through the use of JAXB or Jackson’s provided annotations. When further control is needed, a custom XmlMapper
can be injected through the ObjectMapper
property for cases where custom XML serializers/deserializers need to be provided for specific types. By default this converter supports ( application/xml
).
MappingJackson2XmlHttpMessageConverter
一个HttpMessageConverter实现,可以使用Jackson XML扩展程序的XmlMapper读写XML。通过使用JAXB或Jackson提供的注释,可以根据需要自定义XML映射。当需要进一步控制时,对于需要为特定类型提供自定义XML序列化器/反序列化器的情况,可以通过ObjectMapper属性注入自定义XmlMapper。默认情况下,此转换器支持(application / xml)。
SourceHttpMessageConverter
An HttpMessageConverter
implementation that can read and write javax.xml.transform.Source
from the HTTP request and response. Only DOMSource
, SAXSource
, and StreamSource
are supported. By default, this converter supports ( text/xml
) and ( application/xml
).
SourceHttpMessageConverter
一个HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入javax.xml.transform.Source。仅支持DOMSource,SAXSource和StreamSource。默认情况下,此转换器支持(text / xml)和(application / xml)。
BufferedImageHttpMessageConverter
An HttpMessageConverter
implementation that can read and write java.awt.image.BufferedImage
from the HTTP request and response. This converter reads and writes the media type supported by the Java I/O API.
BufferedImageHttpMessageConverter
HttpMessageConverter实现,可以从HTTP请求和响应中读取和写入java.awt.image.BufferedImage。该转换器读取和写入Java I / O API支持的媒体类型。
28.10.3 Async RestTemplate
28.10.3异步RestTemplate
Web applications often need to query external REST services those days. The very nature of HTTP and synchronous calls can lead up to challenges when scaling applications for those needs: multiple threads may be blocked, waiting for remote HTTP responses.
Web应用程序通常需要查询外部REST服务。 HTTP和同步调用的本质可能导致在扩展应用程序以满足这些需求时遇到挑战:多个线程可能被阻塞,等待远程HTTP响应。
AsyncRestTemplate
and Section 28.10.1, “RestTemplate”'s APIs are very similar; see Table 28.1, “Overview of RestTemplate methods”. The main difference between those APIs is that AsyncRestTemplate
returns ListenableFuture
wrappers as opposed to concrete results.
AsyncRestTemplate和第28.10.1节“ RestTemplate”的API非常相似。 请参见表28.1,“ RestTemplate方法概述”。 这些API之间的主要区别是AsyncRestTemplate返回的ListenableFuture包装器,而不是具体的结果。
The previous RestTemplate
example translates to:
先前的RestTemplate示例转换为:
// async call
Future<ResponseEntity<String>> futureEntity = template.getForEntity(
"http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
// get the concrete result - synchronous call
ResponseEntity<String> entity = futureEntity.get();
ListenableFuture
accepts completion callbacks:
ListenableFuture接受完成回调:
ListenableFuture<ResponseEntity<String>> futureEntity = template.getForEntity(
"http://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
// register a callback
futureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> entity) {
//...
}
@Override
public void onFailure(Throwable t) {
//...
}
});
The default |
默认的AsyncRestTemplate构造函数注册一个SimpleAsyncTaskExecutor来执行HTTP请求。 当处理大量短期请求时,像ThreadPoolTaskExecutor这样的线程池TaskExecutor实现可能是一个不错的选择。
See the ListenableFuture
javadocs and AsyncRestTemplate
javadocs for more details.
有关更多详细信息,请参见ListenableFuture javadocs和AsyncRestTemplate javadocs。