RestTemplate的使用
new RestTemplate().getForObject("http://www.baidu.com", String.class);
源码分析
getForObject()
方法源码:
@Override
@Nullable
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
execute()
方法源码:
@Override
@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
URI expanded = getUriTemplateHandler().expand(url, uriVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
doExecute()方法源码:
@Nullable
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,
@Nullable 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) {
String resource = url.toString();
String query = url.getRawQuery();
resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
throw new ResourceAccessException("I/O error on " + method.name() +
" request for \"" + resource + "\": " + ex.getMessage(), ex);
}
finally {
if (response != null) {
response.close();
}
}
}
AbstractClientHttpRequest类execute()
方法代码实现:
@Override
public final ClientHttpResponse execute() throws IOException {
assertNotExecuted();
ClientHttpResponse result = executeInternal(this.headers);
this.executed = true;
return result;
}
AbstractClientHttpRequest类executeInternal()方法代码实现
@Override
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
byte[] bytes = this.bufferedOutput.toByteArray();
if (headers.getContentLength() < 0) {
headers.setContentLength(bytes.length);
}
ClientHttpResponse result = executeInternal(headers, bytes);
this.bufferedOutput = new ByteArrayOutputStream(0);
return result;
}
@Override
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
return requestExecution.execute(this, bufferedOutput);
}
InterceptingRequestExecution类execute()
方法实现:
@Override
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
//按个遍历拦截器
if (this.iterator.hasNext()) {
ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
return nextInterceptor.intercept(request, body, this);
}
else {
HttpMethod method = request.getMethod();
Assert.state(method != null, "No standard HTTP method");
ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value));
if (body.length > 0) {
if (delegate instanceof StreamingHttpOutputMessage) {
StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate;
streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream));
}
else {
StreamUtils.copy(body, delegate.getBody());
}
}
return delegate.execute();
}
}
需要注意上面这段代码中的RestTemplate拦截器的处理动作,我们自定义的RestTemplate拦截器就是在这个过程中发挥作用的。我们来看下ClientHttpRequestInterceptor的源码:
@FunctionalInterface
public interface ClientHttpRequestInterceptor {
/**
* Intercept the given request, and return a response. The given
* {@link ClientHttpRequestExecution} allows the interceptor to pass on the
* request and response to the next entity in the chain.
* <p>A typical implementation of this method would follow the following pattern:
* <ol>
* <li>Examine the {@linkplain HttpRequest request} and body</li>
* <li>Optionally {@linkplain org.springframework.http.client.support.HttpRequestWrapper
* wrap} the request to filter HTTP attributes.</li>
* <li>Optionally modify the body of the request.</li>
* <li><strong>Either</strong>
* <ul>
* <li>execute the request using
* {@link ClientHttpRequestExecution#execute(org.springframework.http.HttpRequest, byte[])},</li>
* <strong>or</strong>
* <li>do not execute the request to block the execution altogether.</li>
* </ul>
* <li>Optionally wrap the response to filter HTTP attributes.</li>
* </ol>
* @param request the request, containing method, URI, and headers
* @param body the body of the request
* @param execution the request execution
* @return the response
* @throws IOException in case of I/O errors
*/
ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException;
}
我们自己实现一个RestTemplate拦截器:
@Component
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
request.getHeaders().add("token", String.valueOf(System.currentTimeMillis()));
return execution.execute(request, body);
}
}