restTemplate源码解析(三)创建ClientHttpRequest请求对象
所有文章
https://www.cnblogs.com/lay2017/p/11740855.html
正文
上一篇文章中,我们大体看了一下restTemplate的核心逻辑。再回顾一下核心代码
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException { ClientHttpResponse response = null; try { // 生成请求 ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { // 设置header requestCallback.doWithRequest(request); } // 执行请求,获取响应 response = request.execute(); // 处理响应 handleResponse(url, method, response); // 获取响应体对象 return (responseExtractor != null ? responseExtractor.extractData(response) : null); } catch (IOException ex) { // ... 抛出异常 } finally { if (response != null) { // 关闭响应流 response.close(); } } }
本文将打开createRequest这个创建请求的方法,看看创建请求的实现细节
跟进createRequest方法
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { ClientHttpRequest request = getRequestFactory().createRequest(url, method); if (logger.isDebugEnabled()) { logger.debug("HTTP " + method.name() + " " + url); } return request; }
这里是一个工厂模式,先获取一个ClientHttpRequestFactory的工厂实例,然后将创建的工作委托给工厂处理并返回结果。
打开getRequestFactory看看获取的工厂实例(注意:这里不考虑拦截器的部分,所以不向下阅读)
public ClientHttpRequestFactory getRequestFactory() { return this.requestFactory; }
看看requestFactory成员变量
private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
默认是SimpleClientHttpRequestFactory的实现,当然我们可以自定义实现它。简单起见,本文直接看默认的实现。
获取了ClientHttpRequestFactory的实例,我们跟进SimpleClientHttpRequestFactory看看它是怎么实现createRequest方法的
@Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { // 通过URI生成了connection HttpURLConnection connection = openConnection(uri.toURL(), this.proxy); // 对Connection进行一些设置 prepareConnection(connection, httpMethod.name()); // 返回一个ClientHttpRequest的实现 if (this.bufferRequestBody) { return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming); } else { return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming); } }
到这里,我们可以知道SimpleClientHttpRequestFactory其实就是包装了一下HttpUrlConnection。createRequest做了两件事:
1)创建并设置一个HttpUrlConnection
2)构造并返回一个ClientHttpRequest的实例对象
打开openConnection方法看看HttpUrlConnection的创建
protected HttpURLConnection openConnection(URL url, @Nullable Proxy proxy) throws IOException { URLConnection urlConnection = (proxy != null ? url.openConnection(proxy) : url.openConnection()); if (!HttpURLConnection.class.isInstance(urlConnection)) { throw new IllegalStateException("HttpURLConnection required for [" + url + "] but got: " + urlConnection); } return (HttpURLConnection) urlConnection; }
很简单地通过URL对象的openConnection方法返回了一个UrlConnection。
再打开prepareConnection看看设置了啥
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException { if (this.connectTimeout >= 0) { connection.setConnectTimeout(this.connectTimeout); } if (this.readTimeout >= 0) { connection.setReadTimeout(this.readTimeout); } connection.setDoInput(true); if ("GET".equals(httpMethod)) { connection.setInstanceFollowRedirects(true); } else { connection.setInstanceFollowRedirects(false); } if ("POST".equals(httpMethod) || "PUT".equals(httpMethod) || "PATCH".equals(httpMethod) || "DELETE".equals(httpMethod)) { connection.setDoOutput(true); } else { connection.setDoOutput(false); } connection.setRequestMethod(httpMethod); }
也是一些HttpUrlConnection很常见的设置,超时时间,允许输入输出,请求方法啥的
再回到刚刚的createRequest方法
private boolean bufferRequestBody = true; @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { // 通过URI生成了connection HttpURLConnection connection = openConnection(uri.toURL(), this.proxy); // 对Connection进行一些设置 prepareConnection(connection, httpMethod.name()); // 返回一个ClientHttpRequest的实现 if (this.bufferRequestBody) { return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming); } else { return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming); } }
bufferRequestBody默认是true,将会返回ClientHttpRequest的默认实现SimpleBufferingClientHttpRequest的实例对象。
我们保持好奇心,瞄一眼SimpleBufferingClientHttpRequest的类图关系吧。
总结
createRequest方法通过ClientHttpRequestFactory创建并返回了一个ClientHttpRequest的实例。整体逻辑还是挺简单的,如果放到面向过程的代码里或许就是各种ifelse的逻辑。由于我们面向对象,所以会有这些抽象与组合的,习惯于这种代码风格还是挺重要的。