可以发现即使是exchange()方法,最终还是委托给execute/doExecute去执行的:
RestTemplate: // 3个execute方法。最终调用的都是doExecute方法 // 它做的一件事:使用UriTemplateHandler把URL的参数填进去~~~ // 底层使用的是我上文介绍的`UriComponentsBuilder`,还是比较简单的 @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 { ClientHttpResponse response = null; ClientHttpRequest request = createRequest(url, method); // 如果有回调,那就先回调处理一下子请求 if (requestCallback != null) { requestCallback.doWithRequest(request); } // 真正意义上的发送请求。 // 请注意:如果这里的request是`InterceptingClientHttpRequest`,那就回执行拦截器的intercept方法哦~~~ // 至于什么时候是InterceptingClientHttpRequest呢?这个上面有讲的 response = request.execute(); // 处理结果(若有错误,那就抛出异常~~~) handleResponse(url, method, response); // 请求正常。那就使用返回值提取器responseExtractor提取出内容即可了~~~ return (responseExtractor != null ? responseExtractor.extractData(response) : null); ... // 关闭响应(ClientHttpResponse继承了Closeable接口) finally { if (response != null) { response.close(); } } }看完doExecute()的模板式的实现步骤,就清楚了RestTemplate从发出一个请求到收到一个响应的完整过程。Spring设计了多个相关组件,提供钩子程序让我们可以干预到流程里面去,最常见的当然就是请求拦截器了,它在Ribbon负载均衡和Hystrix熔断器里面有很好的应用~
AsyncRestTemplate它是@since 4.0新增的用于解决一些异步Http请求的场景,但它寿命比较短,在Spring5.0就标记为@Deprecated,而被推荐使用WebClient去代替它。
它的实现基础原理是:RestTemplate + SimpleAsyncTaskExecutor任务池的方式去实现的异步请求,返回值均为ListenableFuture。掌握了RestTemplate后,它使用起来是没有什么障碍的
极简使用Demo Show看过了原理的描述,我有理由相信你已经烂熟于胸并对RestTemplate能够运用自如了。因此关于使用方面,本文只给如下非常简单的一个Demo Show我认为是够了的:
public static void main(String[] args) throws IOException { RestTemplate restTemplate = new RestTemplate(); String pageHtml = restTemplate.getForObject("http://www.baidu.com", String.class); System.out.println(pageHtml); // 百度首页的html... }