所有文章
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的邏輯。由於我們面向對象,所以會有這些抽象與組合的,習慣於這種代碼風格還是挺重要的。