RestTemplate介绍
RestTemplate是Spring提供的用于访问Rest服务的客户端,同时RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
RestTemplate初探
通过实例展示RestTemplate的使用
@Test
public void test01(){
RestTemplate restTemplate = new RestTemplate();
String url = "http://www.baidu.com?id={id}&name={name}&num={age}";
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, 1, "Elon", 20);
if(responseEntity.getStatusCode() == HttpStatus.OK){
System.out.println(responseEntity.getBody());
}
}
@Test
public void test02(){
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/api/v1/org/{department}/list");
HttpEntity<String> formEntity = new HttpEntity<String>(getHttpHeaders());
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, formEntity, String.class, 2);
if(responseEntity.getStatusCode() == HttpStatus.OK){
System.out.println(responseEntity.getBody());
}
}
// Mock登录授权信息
public static HttpHeaders getHttpHeaders(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON_UTF8));
headers.add("Cookie", "token=123244545");
return headers;
}
示例参数:
- String url: 该方法第一个参数标识请求的url
- Class<T> responseType: 该参数标识该次HTTP请求的结果映射成的对象类型,
- Object... urlVariables: 该参数用来为url中的参数赋值,支持多个值传递.
RestTemplate的交互说明
上面示例中的交互可以分为三个步骤:
- url和参数聚合
- HTTP请求交互
- HTTP结果映射
对应的SpringRest中的如下方法.
@Override
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor, Object... urlVariables) throws RestClientException {
URI expanded = getUriTemplateHandler().expand(url, urlVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
URL和参数聚合
RestTemplate的源码中使用getUriTemplateHandler().expand(url, urlVariables)
来完善完成URL中占位符参数的聚合。
示例:
@Test
public void url(){
String url = "http://www.baidu.com?id={id}&name={name}&num={age}";
URI expanded = restTemplate.getUriTemplateHandler().expand(url, 1, "Elon", 20);
// 输出结果: http://www.baidu.com?id=1&name=Elon&num=20
System.out.println(expanded.toString());
}
RestTemplate中HTTP交互过程
http交互规范的定义
了解该块前先看看Spring中对ClientHttpRequest和对应的工厂接口的定义
ClientHttpRequest接口的定义
ClientHttpRequest接口的定义很简单,一个钩子方法
public interface ClientHttpRequest extends HttpRequest, HttpOutputMessage {
ClientHttpResponse execute() throws IOException;
}
ClientHttpRequest接口默认提供了如下的扩展类
[图片上传失败...(image-d192aa-1576724583854)]
ClientHttpRequestFactory接口的定义
ClientHttpRequestFactory接口的定义如下:
public interface ClientHttpRequestFactory {
ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}
ClientHttpRequestFactory接口提供的实现类如下:

HttpAccessor的代理实现
Spring中定义了抽象类HttpAccessor, 提供了默认的ClientHttpRequestFactory实现,
ClientHttpRequestFactory默认值为SimpleClientHttpRequestFactory().
对应的HttpAccessor实现的代码:
public abstract class HttpAccessor {
protected final Log logger = LogFactory.getLog(getClass());
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
Assert.notNull(requestFactory, "'requestFactory' must not be null");
this.requestFactory = requestFactory;
}
public ClientHttpRequestFactory getRequestFactory() {
return this.requestFactory;
}
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = getRequestFactory().createRequest(url, method);
if (logger.isDebugEnabled()) {
logger.debug("Created " + method.name() + " request for \"" + url + "\"");
}
return request;
}
}
doExecute中的钩子使用
URL构建完成后RestTemplate调用的是一个doExecute
方法,该方法对应的代码如下
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "'url' must not be null");
Assert.notNull(method, "'method' must not be null");
ClientHttpResponse response = null;
try {
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
response = request.execute();
handleResponse(url, method, response);
if (responseExtractor != null) {
return responseExtractor.extractData(response);
}
else {
return null;
}
}
catch (IOException ex) {
throw new ResourceAccessException("I/O error on " + method.name() +
" request for \"" + url + "\": " + ex.getMessage(), ex);
}
finally {
if (response != null) {
response.close();
}
}
}
这里的createRequest(url, method)
方法集成自抽象类HttpAccessor.这样,在构建完成后,HTTP交互过程交给定义的ClientHttpRequest的规范实现.
HTTP交互结果处理
HTTP交互接口返回通过ResponseExtractor<T>
该规范来处理.
ResponseExtractor<T>接口的定义:
public interface ResponseExtractor<T> {
T extractData(ClientHttpResponse response) throws IOException;
}
ResponseExtractor<T>接口默认提供的实现:
[图片上传失败...(image-130163-1576724583854)]
示例中我们的接口调用的返回结果实现使用的是ResponseEntityResponseExtractor<T>
@Override
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables)
throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = responseEntityExtractor(responseType);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
}
具体的实现可以参看RestTemplate,不再做过多介绍.
RestTemplate类关系图
RestTemplate类关系图
[图片上传失败...(image-171326-1576724583854)]
这里RestTemplate使用的常见的Rest请求的接口都定义在RestOperations中,对应的规范定义如下:
GET 规范
// GET
<T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> T getForObject(URI url, Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
HEAD 规范
// HEAD
HttpHeaders headForHeaders(String url, Object... uriVariables) throws RestClientException;
HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException;
HttpHeaders headForHeaders(URI url) throws RestClientException;
POST 规范
// POST
URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException;
URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
URI postForLocation(URI url, Object request) throws RestClientException;
<T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
throws RestClientException;
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException;
<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
PUT 规范
// PUT
void put(String url, Object request, Object... uriVariables) throws RestClientException;
void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
void put(URI url, Object request) throws RestClientException;
DELETE 规范
// DELETE
void delete(String url, Object... uriVariables) throws RestClientException;
void delete(String url, Map<String, ?> uriVariables) throws RestClientException;
void delete(URI url) throws RestClientException;
OPTIONS 规范
// OPTIONS
Set<HttpMethod> optionsForAllow(String url, Object... uriVariables) throws RestClientException;
Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables) throws RestClientException;
Set<HttpMethod> optionsForAllow(URI url) throws RestClientException;
在提供通用REST(GET、POST、HEAD、PUT、DELETE、OPTIONS)规范操作的基础上还提供了exchange()和execute()相关的规范操作接口定义.
RestTemplate异步模块
AsyncRestTemplate是提供的异步操作RestTemplate的组件快.使用方式比较简单.
@Test
public void test(){
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
String url = "http://www.baidu.com?id={id}&name={name}&num={age}";
ListenableFuture<ResponseEntity<String>> listenableFuture = asyncRestTemplate.getForEntity(url, String.class, 1, "Elon", 20);
try {
ResponseEntity<String> responseEntity = listenableFuture.get();
if(responseEntity.getStatusCode() == HttpStatus.OK){
System.out.println(responseEntity.getBody());
}
} catch (Exception e) {
LOG.error(e.getLocalizedMessage(), e);
}
}
网友评论