HttpClient(二)结构

一、HttpClient结构图

下图来源于对org.apache.httpcomponents:httpclient:4.5.13的源码分析。

image-20211020112411018

二、HttpClient扩展口

1)HttpClientBuilder中有对ClientExecChain的装饰方法

1
2
HttpClientBuilder#decorateMainExec
HttpClientBuilder#decorateProtocolExec

2)HttpClientBuilder中对ProtocolExec请求和响应拦截器的扩展

1
2
3
4
5
HttpClientBuilder#addInterceptorFirst(org.apache.http.HttpRequestInterceptor)
HttpClientBuilder#addInterceptorLast(org.apache.http.HttpRequestInterceptor)

HttpClientBuilder#addInterceptorFirst(org.apache.http.HttpResponseInterceptor)
HttpClientBuilder#addInterceptorLast(org.apache.http.HttpResponseInterceptor)

3)HttpClientBuilder中对RetryExec的RetryHandler进行配置

1
HttpClientBuilderBack#setRetryHandler(org.apache.http.client.HttpRequestRetryHandler)

三、示例

1)HTTP获取服务器证书 - 通过增加ProtocolExec的拦截器实现。代码来源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class HttpClientGetServerCertificate {
public static final String PEER_CERTIFICATES = "PEER_CERTIFICATES";

public static void main(String... args) throws IOException {
// create http response certificate interceptor
HttpResponseInterceptor certificateInterceptor = (httpResponse, context) -> {
ManagedHttpClientConnection routedConnection = (ManagedHttpClientConnection)context.getAttribute(HttpCoreContext.HTTP_CONNECTION);
SSLSession sslSession = routedConnection.getSSLSession();
if (sslSession != null) {

// get the server certificates from the {@Link SSLSession}
Certificate[] certificates = sslSession.getPeerCertificates();

// add the certificates to the context, where we can later grab it from
context.setAttribute(PEER_CERTIFICATES, certificates);
}
};

// create closable http client and assign the certificate interceptor
CloseableHttpClient httpClient = HttpClients.custom().addInterceptorLast(certificateInterceptor).build();

try {

// make HTTP GET request to resource server
HttpGet httpget = new HttpGet("https://www.baidu.com");
System.out.println("Executing request " + httpget.getRequestLine());

// create http context where the certificate will be added
HttpContext context = new BasicHttpContext();
httpClient.execute(httpget, context);

// obtain the server certificates from the context
Certificate[] peerCertificates = (Certificate[])context.getAttribute(PEER_CERTIFICATES);

// loop over certificates and print meta-data
for (Certificate certificate : peerCertificates){
X509Certificate real = (X509Certificate) certificate;
System.out.println("----------------------------------------");
System.out.println("Type: " + real.getType());
System.out.println("Signing Algorithm: " + real.getSigAlgName());
System.out.println("IssuerDN Principal: " + real.getIssuerX500Principal());
System.out.println("SubjectDN Principal: " + real.getSubjectX500Principal());
System.out.println("Not After: " + DateUtils.formatDate(real.getNotAfter(), "dd-MM-yyyy"));
System.out.println("Not Before: " + DateUtils.formatDate(real.getNotBefore(), "dd-MM-yyyy"));
}

} finally {
// close httpclient
httpClient.close();
}
}
}

2)增加异常监听逻辑

1
2
3
4
5
HttpRequestRetryHandler retryHandler = (exception, executionCount, context) -> {
// 可以在此处增加异常监听逻辑
return DefaultHttpRequestRetryHandler.INSTANCE.retryRequest(exception, executionCount, context);
};
clientBuilder.setRetryHandler(retryHandler);

评论