HttpClient

打印 上一主题 下一主题

主题 854|帖子 854|积分 2562

HttpClient

简介

HttpClient是Apache HttpComponents项目中的一个接口。用于发送HTTP请求和接收HTTP响应。
CloseableHttpClient是HttpClient接口的一个具体实现类,提供了自动管理毗连资源的功能,包括毗连的创建、利用和关闭。HttpClient 4.5 之后新增的功能。CloseableHttpClient本身是线程安全的。
实现原理

由于HttpClient组件源码用了大量计划模式,计划模式如果看不懂,解读源码就比较费劲,因此我们通过分析计划模式角度,联合关键代码来解析整个原理的实现。
工厂模式(简化对象创建)

HttpClients类是创建CloseableHttpClient的入口,重要由HttpClients.createDefault()方法创建默认客户端和HttpClients.custom()允许用户配置超时、拦截器、署理等细节,
  1. package org.apache.http.impl.client;
  2. import org.apache.http.conn.HttpClientConnectionManager;
  3. import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
  4. public class HttpClients {
  5.     private HttpClients() {
  6.     }
  7.     public static HttpClientBuilder custom() {
  8.         return HttpClientBuilder.create();
  9.     }
  10.     public static CloseableHttpClient createDefault() {
  11.         return HttpClientBuilder.create().build();
  12.     }
  13.     public static CloseableHttpClient createSystem() {
  14.         return HttpClientBuilder.create().useSystemProperties().build();
  15.     }
  16.     public static CloseableHttpClient createMinimal() {
  17.         return new MinimalHttpClient(new PoolingHttpClientConnectionManager());
  18.     }
  19.     public static CloseableHttpClient createMinimal(HttpClientConnectionManager connManager) {
  20.         return new MinimalHttpClient(connManager);
  21.     }
  22. }
复制代码
制作者模式(机动配置客户端)

从HttpClients类的代码看,HttpClients.custom()返回的是一个HttpClientBuilder对象,支持链式调用配置选项。
装饰器模式(动态扩展功能)

CloseableHttpClient 支持通过拦截器对请求和响应进行增强功能,例如日记记录、认证、缓存等。拦截器本质上是对原有请求/响应处置处罚逻辑的装饰。
HttpClients构建CloseableHttpClient添加拦截增强示例代码如下
  1. CloseableHttpClient httpClient = HttpClients.custom()
  2.     .addInterceptorFirst((HttpRequestInterceptor) (request, context) -> {
  3.         System.out.println("请求 URI: " + request.getRequestLine().getUri());
  4.     })
  5.     .addInterceptorFirst((HttpResponseInterceptor) (response, context) -> {
  6.         System.out.println("响应状态: " + response.getStatusLine().getStatusCode());
  7.     })
  8.     .build();
复制代码
HttpClientBuilder类添加拦截器增强功能相关代码如下
  1.    public final HttpClientBuilder addInterceptorFirst(HttpResponseInterceptor itcp) {
  2.         if (itcp == null) {
  3.             return this;
  4.         } else {
  5.             if (this.responseFirst == null) {
  6.                 this.responseFirst = new LinkedList();
  7.             }
  8.             this.responseFirst.addFirst(itcp);
  9.             return this;
  10.         }
  11.     }
  12.     public final HttpClientBuilder addInterceptorLast(HttpResponseInterceptor itcp) {
  13.         if (itcp == null) {
  14.             return this;
  15.         } else {
  16.             if (this.responseLast == null) {
  17.                 this.responseLast = new LinkedList();
  18.             }
  19.             this.responseLast.addLast(itcp);
  20.             return this;
  21.         }
  22.     }
复制代码
计谋模式(支持差别行为计谋)

比如配置差别的重试计谋,将行为的实现和逻辑分离,便于扩展或切换差别计谋,进步机动性。
  1. HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(3, true);
  2. CloseableHttpClient httpClient = HttpClients.custom()
  3.     .setRetryHandler(retryHandler)
  4.     .build();
复制代码
单例模式(高效管理共享资源)

毗连池管理器(PoolingHttpClientConnectionManager)常被计划为单例,以便多个线程共享雷同的毗连池实例:
  1. java
  2. 复制代码
  3. private static final PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
  4. public static CloseableHttpClient createClient() {
  5.     return HttpClients.custom()
  6.         .setConnectionManager(connectionManager)
  7.         .build();
  8. }
复制代码

  • 确保毗连池资源的统一管理,避免重复创建。
  • 进步资源利用率,降低系统开销。
责任链模式(分阶段处置处罚请求和响应)

ClientExecChain接口
  1. public interface ClientExecChain {
  2.     CloseableHttpResponse execute(HttpRoute var1, HttpRequestWrapper var2, HttpClientContext var3, HttpExecutionAware var4) throws IOException, HttpException;
  3. }
复制代码
HttpClientBuilder.build()方法简化示例代码
  1. public class DefaultHttpClientBuilder {
  2.     public CloseableHttpClient build() {
  3.         HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
  4.         // 最终处理器:MainClientExec
  5.         ClientExecChain mainExec = new MainClientExec(connManager);
  6.         // 第二个处理器:RedirectExec
  7.         ClientExecChain redirectExec = new RedirectExec(mainExec);
  8.         // 第一个处理器:RetryExec
  9.         ClientExecChain retryExec = new RetryExec(redirectExec, new DefaultHttpRequestRetryHandler());
  10.         // 组装完成的责任链起点
  11.         return new InternalHttpClient(retryExec, connManager);
  12.     }
  13. }
复制代码
模板方法模式(定义固定流程,允许定制化)

CloseableHttpClient抽象类中execute()
固定的执行流程

  • 模板方法是 execute():

    • 对 HTTP 请求进行参数校验。
    • 转换请求对象(如 HttpUriRequest -> HttpRequest)。
    • 调用具体实现方法 doExecute()。

  • 子类只需要实现 doExecute() 方法即可完成具体的请求发送逻辑,具体的字类InternalHttpClient类实现doExecute()方法通过责任链模式处置处罚各种逻辑,如重试、重定向和毗连管理。
  1. public abstract class CloseableHttpClient implements HttpClient, Closeable {
  2.     // 抽象方法:由子类实现实际的请求发送逻辑
  3.     protected abstract CloseableHttpResponse doExecute(
  4.             HttpHost target, HttpRequest request, HttpContext context) throws IOException;
  5.     // 模板方法:对外暴露的执行方法
  6.     public CloseableHttpResponse execute(HttpUriRequest request) throws IOException {
  7.         return execute(request, (HttpContext) null);
  8.     }
  9.     public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) throws IOException, ClientProtocolException {
  10.         Args.notNull(request, "HTTP request");//参数校验
  11.         return this.doExecute(determineTarget(request), request, context);//转换请求对象
  12.     }
  13.     public CloseableHttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws IOException {
  14.         Args.notNull(request, "HTTP request");  // 参数校验
  15.         return doExecute(target, request, context);  // 调用抽象方法
  16.     }
  17. }
复制代码
署理模式(管理底层资源和署理请求)

HttpRoutePlanner接口,DefaultRoutePlanner类 实现HttpRoutePlanner接口,DefaultProxyRoutePlanner 和 SystemDefaultRoutePlanner 继续 DefaultRoutePlanner 类。

  • 静态署理
DefaultProxyRoutePlanner 静态署理,所有请求都通过固定的署理服务器转发。
  1. HttpHost proxy = new HttpHost("proxy.example.com", 8080); // 配置代理服务器
  2. CloseableHttpClient httpClient = HttpClients.custom()
  3.         .setRoutePlanner(new DefaultProxyRoutePlanner(proxy)) // 设置静态代理
  4.         .build();
  5. HttpGet request = new HttpGet("http://example.com");
  6. CloseableHttpResponse response = httpClient.execute(request);
  7. System.out.println(EntityUtils.toString(response.getEntity()));
复制代码

  • 动态署理
DefaultRoutePlanner 或 SystemDefaultRoutePlanner 根据目的主机或系统设置动态选择署理。
当创建 SystemDefaultRoutePlanner 时,会指定一个 ProxySelector 对象:示例代码如下
  1. ProxySelector selector = ProxySelector.getDefault();
  2. SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(selector);
复制代码
在 SystemDefaultRoutePlanner.determineProxy() 方法中,会调用 ProxySelector.select(),返回一组署理(大概是多个,遍历署理列表,按照优先级选出合适的署理。动态选择署理,示例代码如下
  1. @Override
  2. protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
  3.     if (target == null) {
  4.         throw new IllegalArgumentException("Target host is null");
  5.     }
  6.     // 使用目标主机的 URI 创建请求
  7.     URI targetURI = URI.create(target.toURI());
  8.     List<Proxy> proxies = proxySelector.select(targetURI);  // 调用 ProxySelector
  9.     Proxy proxy = chooseProxy(proxies);
  10.     if (proxy == null || proxy.type() == Proxy.Type.DIRECT) {
  11.         return null; // 无代理,直接连接
  12.     }
  13.     if (proxy.type() == Proxy.Type.HTTP) {
  14.         InetSocketAddress address = (InetSocketAddress) proxy.address();
  15.         return new HttpHost(address.getHostString(), address.getPort());
  16.     } else {
  17.         throw new HttpException("Unsupported proxy type: " + proxy.type());
  18.     }
  19. }
复制代码
总结

利用多种计划模式的联合使得 CloseableHttpClient具备高扩展性、机动性和性能上风,能够满足各种复杂的 HTTP 通讯场景需求。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

我爱普洱茶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表