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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM