欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

RestTemplate對HttpClient的適配源碼解讀

 更新時間:2023年10月09日 08:36:48   作者:codecraft  
這篇文章主要為大家介紹了RestTemplate對HttpClient的適配源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下RestTemplate對HttpClient的適配

ClientHttpRequestFactory

org/springframework/http/client/ClientHttpRequestFactory.java

/**
 * Factory for {@link ClientHttpRequest} objects.
 * Requests are created by the {@link #createRequest(URI, HttpMethod)} method.
 *
 * @author Arjen Poutsma
 * @since 3.0
 */
@FunctionalInterface
public interface ClientHttpRequestFactory {
    /**
     * Create a new {@link ClientHttpRequest} for the specified URI and HTTP method.
     * <p>The returned request can be written to, and then executed by calling
     * {@link ClientHttpRequest#execute()}.
     * @param uri the URI to create a request for
     * @param httpMethod the HTTP method to execute
     * @return the created request
     * @throws IOException in case of I/O errors
     */
    ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException;
}
spring-web定義了ClientHttpRequestFactory接口,它定義了一個createRequest方法

HttpComponentsClientHttpRequestFactory

org/springframework/http/client/HttpComponentsClientHttpRequestFactory.java

public class HttpComponentsClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean {
    private HttpClient httpClient;
    @Nullable
    private RequestConfig requestConfig;
    private boolean bufferRequestBody = true;
    /**
     * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
     * with a default {@link HttpClient} based on system properties.
     */
    public HttpComponentsClientHttpRequestFactory() {
        this.httpClient = HttpClients.createSystem();
    }
    /**
     * Create a new instance of the {@code HttpComponentsClientHttpRequestFactory}
     * with the given {@link HttpClient} instance.
     * @param httpClient the HttpClient instance to use for this request factory
     */
    public HttpComponentsClientHttpRequestFactory(HttpClient httpClient) {
        this.httpClient = httpClient;
    }
    @Override
    public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
        HttpClient client = getHttpClient();
        HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);
        postProcessHttpRequest(httpRequest);
        HttpContext context = createHttpContext(httpMethod, uri);
        if (context == null) {
            context = HttpClientContext.create();
        }
        // Request configuration not set in the context
        if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {
            // Use request configuration given by the user, when available
            RequestConfig config = null;
            if (httpRequest instanceof Configurable) {
                config = ((Configurable) httpRequest).getConfig();
            }
            if (config == null) {
                config = createRequestConfig(client);
            }
            if (config != null) {
                context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);
            }
        }
        if (this.bufferRequestBody) {
            return new HttpComponentsClientHttpRequest(client, httpRequest, context);
        }
        else {
            return new HttpComponentsStreamingClientHttpRequest(client, httpRequest, context);
        }
    }
 /**
     * Shutdown hook that closes the underlying
     * {@link org.apache.http.conn.HttpClientConnectionManager ClientConnectionManager}'s
     * connection pool, if any.
     */
    @Override
    public void destroy() throws Exception {
        HttpClient httpClient = getHttpClient();
        if (httpClient instanceof Closeable) {
            ((Closeable) httpClient).close();
        }
    }
    //......
}
HttpComponentsClientHttpRequestFactory實現(xiàn)了ClientHttpRequestFactory及DisposableBean接口;createRequest方法先拿到httpClient,然后創(chuàng)建createHttpUriRequest,設(shè)置RequestConfig,針對bufferRequestBody的場景HttpComponentsClientHttpRequest,否則創(chuàng)建HttpComponentsStreamingClientHttpRequest;destroy方法主要是關(guān)閉httpClient

ClientHttpRequest

org/springframework/http/client/ClientHttpRequest.java

public interface ClientHttpRequest extends HttpRequest, HttpOutputMessage {
    /**
     * Execute this request, resulting in a {@link ClientHttpResponse} that can be read.
     * @return the response result of the execution
     * @throws IOException in case of I/O errors
     */
    ClientHttpResponse execute() throws IOException;
}
ClientHttpRequest接口定義了execute方法,它返回ClientHttpResponse

HttpComponentsClientHttpRequest

org/springframework/http/client/HttpComponentsClientHttpRequest.java

final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpRequest {
    private final HttpClient httpClient;
    private final HttpUriRequest httpRequest;
    private final HttpContext httpContext;
    HttpComponentsClientHttpRequest(HttpClient client, HttpUriRequest request, HttpContext context) {
        this.httpClient = client;
        this.httpRequest = request;
        this.httpContext = context;
    }
    @Override
    public String getMethodValue() {
        return this.httpRequest.getMethod();
    }
    @Override
    public URI getURI() {
        return this.httpRequest.getURI();
    }
    HttpContext getHttpContext() {
        return this.httpContext;
    }
    @Override
    protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
        addHeaders(this.httpRequest, headers);
        if (this.httpRequest instanceof HttpEntityEnclosingRequest) {
            HttpEntityEnclosingRequest entityEnclosingRequest = (HttpEntityEnclosingRequest) this.httpRequest;
            HttpEntity requestEntity = new ByteArrayEntity(bufferedOutput);
            entityEnclosingRequest.setEntity(requestEntity);
        }
        HttpResponse httpResponse = this.httpClient.execute(this.httpRequest, this.httpContext);
        return new HttpComponentsClientHttpResponse(httpResponse);
    }
    /**
     * Add the given headers to the given HTTP request.
     * @param httpRequest the request to add the headers to
     * @param headers the headers to add
     */
    static void addHeaders(HttpUriRequest httpRequest, HttpHeaders headers) {
        headers.forEach((headerName, headerValues) -> {
            if (HttpHeaders.COOKIE.equalsIgnoreCase(headerName)) {  // RFC 6265
                String headerValue = StringUtils.collectionToDelimitedString(headerValues, "; ");
                httpRequest.addHeader(headerName, headerValue);
            }
            else if (!HTTP.CONTENT_LEN.equalsIgnoreCase(headerName) &&
                    !HTTP.TRANSFER_ENCODING.equalsIgnoreCase(headerName)) {
                for (String headerValue : headerValues) {
                    httpRequest.addHeader(headerName, headerValue);
                }
            }
        });
    }
}
HttpComponentsClientHttpRequest繼承了AbstractBufferingClientHttpRequest,其executeInternal方法調(diào)用httpClient.execute,然后返回HttpComponentsClientHttpResponse

HttpComponentsStreamingClientHttpRequest

org/springframework/http/client/HttpComponentsStreamingClientHttpRequest.java

final class HttpComponentsStreamingClientHttpRequest extends AbstractClientHttpRequest
        implements StreamingHttpOutputMessage {
    private final HttpClient httpClient;
    private final HttpUriRequest httpRequest;
    private final HttpContext httpContext;
    @Nullable
    private Body body;
    HttpComponentsStreamingClientHttpRequest(HttpClient client, HttpUriRequest request, HttpContext context) {
        this.httpClient = client;
        this.httpRequest = request;
        this.httpContext = context;
    }
    @Override
    public String getMethodValue() {
        return this.httpRequest.getMethod();
    }
    @Override
    public URI getURI() {
        return this.httpRequest.getURI();
    }
    @Override
    public void setBody(Body body) {
        assertNotExecuted();
        this.body = body;
    }
    @Override
    protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
        throw new UnsupportedOperationException("getBody not supported");
    }
    @Override
    protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
        HttpComponentsClientHttpRequest.addHeaders(this.httpRequest, headers);
        if (this.httpRequest instanceof HttpEntityEnclosingRequest && this.body != null) {
            HttpEntityEnclosingRequest entityEnclosingRequest = (HttpEntityEnclosingRequest) this.httpRequest;
            HttpEntity requestEntity = new StreamingHttpEntity(getHeaders(), this.body);
            entityEnclosingRequest.setEntity(requestEntity);
        }
        HttpResponse httpResponse = this.httpClient.execute(this.httpRequest, this.httpContext);
        return new HttpComponentsClientHttpResponse(httpResponse);
    }
    //......
}
HttpComponentsStreamingClientHttpRequest繼承了AbstractClientHttpRequest,實現(xiàn)了StreamingHttpOutputMessage接口,其getBodyInternal拋出UnsupportedOperationException,其executeInternal方法創(chuàng)建的是StreamingHttpEntity,然后執(zhí)行httpClient.execute(this.httpRequest, this.httpContext),最后返回HttpComponentsClientHttpResponse

ClientHttpResponse

org/springframework/http/client/ClientHttpResponse.java

/**
 * Represents a client-side HTTP response.
 * Obtained via an calling of the {@link ClientHttpRequest#execute()}.
 *
 * <p>A {@code ClientHttpResponse} must be {@linkplain #close() closed},
 * typically in a {@code finally} block.
 *
 * @author Arjen Poutsma
 * @since 3.0
 */
public interface ClientHttpResponse extends HttpInputMessage, Closeable {
    /**
     * Return the HTTP status code as an {@link HttpStatus} enum value.
     * @return the HTTP status as an HttpStatus enum value (never {@code null})
     * @throws IOException in case of I/O errors
     * @throws IllegalArgumentException in case of an unknown HTTP status code
     * @since #getRawStatusCode()
     * @see HttpStatus#valueOf(int)
     */
    HttpStatus getStatusCode() throws IOException;
    /**
     * Return the HTTP status code (potentially non-standard and not
     * resolvable through the {@link HttpStatus} enum) as an integer.
     * @return the HTTP status as an integer value
     * @throws IOException in case of I/O errors
     * @since 3.1.1
     * @see #getStatusCode()
     * @see HttpStatus#resolve(int)
     */
    int getRawStatusCode() throws IOException;
    /**
     * Return the HTTP status text of the response.
     * @return the HTTP status text
     * @throws IOException in case of I/O errors
     */
    String getStatusText() throws IOException;
    /**
     * Close this response, freeing any resources created.
     */
    @Override
    void close();
}
ClientHttpResponse接口定義了getStatusCode、getRawStatusCode、getStatusText、close方法

HttpComponentsClientHttpResponse

org/springframework/http/client/HttpComponentsClientHttpResponse.java

final class HttpComponentsClientHttpResponse extends AbstractClientHttpResponse {
    private final HttpResponse httpResponse;
    @Nullable
    private HttpHeaders headers;
    HttpComponentsClientHttpResponse(HttpResponse httpResponse) {
        this.httpResponse = httpResponse;
    }
    @Override
    public int getRawStatusCode() throws IOException {
        return this.httpResponse.getStatusLine().getStatusCode();
    }
    @Override
    public String getStatusText() throws IOException {
        return this.httpResponse.getStatusLine().getReasonPhrase();
    }
    @Override
    public HttpHeaders getHeaders() {
        if (this.headers == null) {
            this.headers = new HttpHeaders();
            for (Header header : this.httpResponse.getAllHeaders()) {
                this.headers.add(header.getName(), header.getValue());
            }
        }
        return this.headers;
    }
    @Override
    public InputStream getBody() throws IOException {
        HttpEntity entity = this.httpResponse.getEntity();
        return (entity != null ? entity.getContent() : StreamUtils.emptyInput());
    }
    @Override
    public void close() {
        // Release underlying connection back to the connection manager
        try {
            try {
                // Attempt to keep connection alive by consuming its remaining content
                EntityUtils.consume(this.httpResponse.getEntity());
            }
            finally {
                if (this.httpResponse instanceof Closeable) {
                    ((Closeable) this.httpResponse).close();
                }
            }
        }
        catch (IOException ex) {
            // Ignore exception on close...
        }
    }
}
HttpComponentsClientHttpResponse繼承了AbstractClientHttpResponse,其getBody方法返回的是httpResponse.getEntity().getContent()或者StreamUtils.emptyInput(),其close方法主要是執(zhí)行EntityUtils.consume(this.httpResponse.getEntity())以及((Closeable) this.httpResponse).close()

小結(jié)

spring-web定義了ClientHttpRequestFactory接口,它定義了一個createRequest方法,HttpComponentsClientHttpRequestFactory就是RestTemplate對HttpClient的適配,其通過HttpComponentsClientHttpRequest或者HttpComponentsStreamingClientHttpRequest,將HttpClient的request適配為了spring-web的ClientHttpRequest,將response通過HttpComponentsClientHttpResponse適配為spring-web的ClientHttpResponse。

以上就是RestTemplate對HttpClient的適配的詳細(xì)內(nèi)容,更多關(guān)于RestTemplate HttpClient適配的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱

    MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱

    MyBatis是一個支持普通SQL查詢,存儲過程和高級映射的優(yōu)秀持久層框架,MyBatis越來越受大家的喜愛了。下面給大家分享MyBatis使用動態(tài)SQL標(biāo)簽的小陷阱,感興趣的朋友一起看看吧
    2016-10-10
  • 利用Springboot+Caffeine實現(xiàn)本地緩存實例代碼

    利用Springboot+Caffeine實現(xiàn)本地緩存實例代碼

    Caffeine是一個基于Java8開發(fā)的提供了近乎最佳命中率的高性能的緩存庫,下面這篇文章主要給大家介紹了關(guān)于利用Springboot+Caffeine實現(xiàn)本地緩存的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • spring boot基于注解的聲明式事務(wù)配置詳解

    spring boot基于注解的聲明式事務(wù)配置詳解

    這篇文章主要介紹了spring boot基于注解的聲明式事務(wù)配置詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java創(chuàng)建數(shù)組、賦值的四種方式詳解(聲明+創(chuàng)建+初始化?)

    Java創(chuàng)建數(shù)組、賦值的四種方式詳解(聲明+創(chuàng)建+初始化?)

    數(shù)組是一種數(shù)據(jù)結(jié)構(gòu),用來存儲同一類型值的集合一旦創(chuàng)建了數(shù)組,就不能再改變它的長度,下面這篇文章主要給大家介紹了關(guān)于Java創(chuàng)建數(shù)組、賦值的四種方式(聲明+創(chuàng)建+初始化?)的相關(guān)資料,需要的朋友可以參考下
    2024-04-04
  • Java Web 簡單的分頁顯示實例代碼

    Java Web 簡單的分頁顯示實例代碼

    這篇文章主要介紹了Java Web 簡單的分頁顯示實例代碼的相關(guān)資料,本文通過,計算總的頁數(shù)和查詢指定頁數(shù)據(jù)兩個方法實現(xiàn)分頁效果,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • SpringBoot接口防抖(防重復(fù)提交)的實現(xiàn)方案

    SpringBoot接口防抖(防重復(fù)提交)的實現(xiàn)方案

    所謂防抖,一是防用戶手抖,二是防網(wǎng)絡(luò)抖動,在Web系統(tǒng)中,表單提交是一個非常常見的功能,如果不加控制,容易因為用戶的誤操作或網(wǎng)絡(luò)延遲導(dǎo)致同一請求被發(fā)送多次,所以本文給大家介紹了SpringBoot接口防抖(防重復(fù)提交)的實現(xiàn)方案,需要的朋友可以參考下
    2024-04-04
  • IDEA編譯時報常量字符串過長的解決辦法

    IDEA編譯時報常量字符串過長的解決辦法

    本文主要介紹了IDEA編譯時報常量字符串過長的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Spring事務(wù)管理的使用細(xì)則淺析

    Spring事務(wù)管理的使用細(xì)則淺析

    事務(wù)的作用就是為了保證用戶的每一個操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們在使用Spring開發(fā)應(yīng)用時,大部分情況下也都需要使用事務(wù)
    2023-02-02
  • 解決SSLContext.getInstance()中參數(shù)設(shè)置TLS版本無效的問題

    解決SSLContext.getInstance()中參數(shù)設(shè)置TLS版本無效的問題

    這篇文章主要介紹了解決SSLContext.getInstance()中參數(shù)設(shè)置TLS版本無效的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java實現(xiàn)給網(wǎng)站上傳圖片蓋章的方法

    Java實現(xiàn)給網(wǎng)站上傳圖片蓋章的方法

    這篇文章主要介紹了Java實現(xiàn)給網(wǎng)站上傳圖片蓋章的方法,涉及java針對圖片的合成操作技巧,類似水印功能,需要的朋友可以參考下
    2015-07-07

最新評論