HttpClient
简介
HttpClient是Apache HttpComponents项目中的一个接口。用于发送HTTP请求和接收HTTP响应。
CloseableHttpClient是HttpClient接口的一个具体实现类,提供了自动管理毗连资源的功能,包括毗连的创建、利用和关闭。HttpClient 4.5 之后新增的功能。CloseableHttpClient本身是线程安全的。
实现原理
由于HttpClient组件源码用了大量计划模式,计划模式如果看不懂,解读源码就比较费劲,因此我们通过分析计划模式角度,联合关键代码来解析整个原理的实现。
工厂模式(简化对象创建)
HttpClients类是创建CloseableHttpClient的入口,重要由HttpClients.createDefault()方法创建默认客户端和HttpClients.custom()允许用户配置超时、拦截器、署理等细节,- package org.apache.http.impl.client;
- import org.apache.http.conn.HttpClientConnectionManager;
- import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
- public class HttpClients {
- private HttpClients() {
- }
- public static HttpClientBuilder custom() {
- return HttpClientBuilder.create();
- }
- public static CloseableHttpClient createDefault() {
- return HttpClientBuilder.create().build();
- }
- public static CloseableHttpClient createSystem() {
- return HttpClientBuilder.create().useSystemProperties().build();
- }
- public static CloseableHttpClient createMinimal() {
- return new MinimalHttpClient(new PoolingHttpClientConnectionManager());
- }
- public static CloseableHttpClient createMinimal(HttpClientConnectionManager connManager) {
- return new MinimalHttpClient(connManager);
- }
- }
复制代码 制作者模式(机动配置客户端)
从HttpClients类的代码看,HttpClients.custom()返回的是一个HttpClientBuilder对象,支持链式调用配置选项。
装饰器模式(动态扩展功能)
CloseableHttpClient 支持通过拦截器对请求和响应进行增强功能,例如日记记录、认证、缓存等。拦截器本质上是对原有请求/响应处置处罚逻辑的装饰。
HttpClients构建CloseableHttpClient添加拦截增强示例代码如下- CloseableHttpClient httpClient = HttpClients.custom()
- .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
- System.out.println("请求 URI: " + request.getRequestLine().getUri());
- })
- .addInterceptorFirst((HttpResponseInterceptor) (response, context) -> {
- System.out.println("响应状态: " + response.getStatusLine().getStatusCode());
- })
- .build();
复制代码 HttpClientBuilder类添加拦截器增强功能相关代码如下- public final HttpClientBuilder addInterceptorFirst(HttpResponseInterceptor itcp) {
- if (itcp == null) {
- return this;
- } else {
- if (this.responseFirst == null) {
- this.responseFirst = new LinkedList();
- }
- this.responseFirst.addFirst(itcp);
- return this;
- }
- }
- public final HttpClientBuilder addInterceptorLast(HttpResponseInterceptor itcp) {
- if (itcp == null) {
- return this;
- } else {
- if (this.responseLast == null) {
- this.responseLast = new LinkedList();
- }
- this.responseLast.addLast(itcp);
- return this;
- }
- }
复制代码 计谋模式(支持差别行为计谋)
比如配置差别的重试计谋,将行为的实现和逻辑分离,便于扩展或切换差别计谋,进步机动性。- HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(3, true);
- CloseableHttpClient httpClient = HttpClients.custom()
- .setRetryHandler(retryHandler)
- .build();
复制代码 单例模式(高效管理共享资源)
毗连池管理器(PoolingHttpClientConnectionManager)常被计划为单例,以便多个线程共享雷同的毗连池实例:- java
- 复制代码
- private static final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
- public static CloseableHttpClient createClient() {
- return HttpClients.custom()
- .setConnectionManager(connectionManager)
- .build();
- }
复制代码
- 确保毗连池资源的统一管理,避免重复创建。
- 进步资源利用率,降低系统开销。
责任链模式(分阶段处置处罚请求和响应)
ClientExecChain接口- public interface ClientExecChain {
- CloseableHttpResponse execute(HttpRoute var1, HttpRequestWrapper var2, HttpClientContext var3, HttpExecutionAware var4) throws IOException, HttpException;
- }
复制代码 HttpClientBuilder.build()方法简化示例代码- public class DefaultHttpClientBuilder {
- public CloseableHttpClient build() {
- HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
- // 最终处理器:MainClientExec
- ClientExecChain mainExec = new MainClientExec(connManager);
- // 第二个处理器:RedirectExec
- ClientExecChain redirectExec = new RedirectExec(mainExec);
- // 第一个处理器:RetryExec
- ClientExecChain retryExec = new RetryExec(redirectExec, new DefaultHttpRequestRetryHandler());
- // 组装完成的责任链起点
- return new InternalHttpClient(retryExec, connManager);
- }
- }
复制代码 模板方法模式(定义固定流程,允许定制化)
CloseableHttpClient抽象类中execute()
固定的执行流程
- 模板方法是 execute():
- 对 HTTP 请求进行参数校验。
- 转换请求对象(如 HttpUriRequest -> HttpRequest)。
- 调用具体实现方法 doExecute()。
- 子类只需要实现 doExecute() 方法即可完成具体的请求发送逻辑,具体的字类InternalHttpClient类实现doExecute()方法通过责任链模式处置处罚各种逻辑,如重试、重定向和毗连管理。
- public abstract class CloseableHttpClient implements HttpClient, Closeable {
- // 抽象方法:由子类实现实际的请求发送逻辑
- protected abstract CloseableHttpResponse doExecute(
- HttpHost target, HttpRequest request, HttpContext context) throws IOException;
- // 模板方法:对外暴露的执行方法
- public CloseableHttpResponse execute(HttpUriRequest request) throws IOException {
- return execute(request, (HttpContext) null);
- }
- public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException, ClientProtocolException {
- Args.notNull(request, "HTTP request");//参数校验
- return this.doExecute(determineTarget(request), request, context);//转换请求对象
- }
- public CloseableHttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
- Args.notNull(request, "HTTP request"); // 参数校验
- return doExecute(target, request, context); // 调用抽象方法
- }
- }
复制代码 署理模式(管理底层资源和署理请求)
HttpRoutePlanner接口,DefaultRoutePlanner类 实现HttpRoutePlanner接口,DefaultProxyRoutePlanner 和 SystemDefaultRoutePlanner 继续 DefaultRoutePlanner 类。
DefaultProxyRoutePlanner 静态署理,所有请求都通过固定的署理服务器转发。- HttpHost proxy = new HttpHost("proxy.example.com", 8080); // 配置代理服务器
- CloseableHttpClient httpClient = HttpClients.custom()
- .setRoutePlanner(new DefaultProxyRoutePlanner(proxy)) // 设置静态代理
- .build();
- HttpGet request = new HttpGet("http://example.com");
- CloseableHttpResponse response = httpClient.execute(request);
- System.out.println(EntityUtils.toString(response.getEntity()));
复制代码 DefaultRoutePlanner 或 SystemDefaultRoutePlanner 根据目的主机或系统设置动态选择署理。
当创建 SystemDefaultRoutePlanner 时,会指定一个 ProxySelector 对象:示例代码如下- ProxySelector selector = ProxySelector.getDefault();
- SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(selector);
复制代码 在 SystemDefaultRoutePlanner.determineProxy() 方法中,会调用 ProxySelector.select(),返回一组署理(大概是多个,遍历署理列表,按照优先级选出合适的署理。动态选择署理,示例代码如下- @Override
- protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
- if (target == null) {
- throw new IllegalArgumentException("Target host is null");
- }
- // 使用目标主机的 URI 创建请求
- URI targetURI = URI.create(target.toURI());
- List<Proxy> proxies = proxySelector.select(targetURI); // 调用 ProxySelector
- Proxy proxy = chooseProxy(proxies);
- if (proxy == null || proxy.type() == Proxy.Type.DIRECT) {
- return null; // 无代理,直接连接
- }
- if (proxy.type() == Proxy.Type.HTTP) {
- InetSocketAddress address = (InetSocketAddress) proxy.address();
- return new HttpHost(address.getHostString(), address.getPort());
- } else {
- throw new HttpException("Unsupported proxy type: " + proxy.type());
- }
- }
复制代码 总结
利用多种计划模式的联合使得 CloseableHttpClient具备高扩展性、机动性和性能上风,能够满足各种复杂的 HTTP 通讯场景需求。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |