首页 > 其他分享 >HttpClient5升级笔记--API篇

HttpClient5升级笔记--API篇

时间:2023-12-25 17:04:22浏览次数:20  
标签:HttpClient5 HTTP 请求 -- 代码 API public HttpClient

最近终于是安奈不住升级的冲动,将自己项目的HttpClient版本从4升级到了5,其过程不可谓不艰辛,很多API改动让人无从下手。

Apache HttpClient 5(也称为 HttpClient 5.x)是 Apache HttpComponents 项目中的一个重要组件,用于发送 HTTP 请求和处理 HTTP 响应。它在与网络通信和处理方面提供了许多优势:

  1. 模块化设计: HttpClient 5 采用了模块化的设计,将核心功能拆分为不同的模块。这种设计使得用户可以根据自己的需求选择性地引入和使用不同的功能模块,从而降低了依赖的复杂性。
  2. 高度可定制: 提供了丰富的配置选项和可定制性,允许开发人员根据特定需求配置连接管理、超时、代理、安全策略等参数。
  3. 异步支持: 提供了对异步请求的支持,可以利用异步方式发送请求并处理响应,有助于提高系统的并发能力和性能。
  4. 优化的连接管理: 引入了更灵活和高效的连接管理机制,包括连接池管理、连接复用,可有效减少连接的建立和关闭次数,提高资源利用率。
  5. HTTP/2 支持: 支持 HTTP/2 协议,允许客户端使用 HTTP/2 进行通信,提高了性能和效率,尤其是在处理大量并行请求时。
  6. 最新的标准和协议支持: 支持最新的 HTTP 标准和协议,包括 HTTP/1.1、HTTP/2、TLS/SSL 等,使得 HttpClient 5 在安全性和性能方面都能够保持更新和竞争力。
  7. 优化的代码结构和性能: 重新设计和优化的代码结构,使得 HttpClient 5 在处理请求和响应时更加高效和可靠。
  8. 易于使用的 API: 提供了简单易用的 API,使得发送 HTTP 请求和处理响应变得更加直观和简单。

针对以上好处,本人仅仅感受到了一点点,但是成本远高于好处,经过简单自测,整体感觉没有质的提升。唯一吸引我的还是HTTP/2的支持,不过本地没有开发该协议接口,暂时还没测试,目前主流还是HTTP 1.1。

这是FunTester项目中升级到HttpClient 5的依赖版本。

        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
            <version>5.3</version>
        </dependency>

其中依赖版本不变,如果你项目里面其他库依赖了HttpClient 4.x版本,记得排除掉,避免干扰。

下面开始分享API改动点,内容不分先后,按照我FunTester项目从上至下列举。以下问容中旧版本指的是4.x,新版指的是5.3。

包名

包名改成了 org.apache.hc.client5. 开头的,需要不少手动工作量。

重试

在旧版本中叫HttpRequestRetryHandler,新版本叫做HttpRequestRetryStrategy,中文应该是重测策略。实现方法上也有所不同。旧版本方法 public boolean retryRequest(IOException exception, int executionCount, HttpContext context) ,而新版本需要实现多个方法: public boolean retryRequest(HttpRequest httpRequest, IOException e, int i, HttpContext httpContext)public boolean retryRequest(HttpResponse httpResponse, int i, HttpContext httpContext)public TimeValue getRetryInterval(HttpResponse httpResponse, int i, HttpContext httpContext) 第一个方法跟旧接口很相似,代码直接可以套用。第二个方法用于对响应信息进行判断重试,这个方法挺不错的,很有市场。第三个方法获取重试间隔,由于我并没有设置改功能,所以并没有什么用。但是大家注意引入了新类 org.apache.hc.core5.util.TimeValue ,在HttpClient 5中,大量使用这个类作为时间配置。

连接配置

新的版本取消了一批API,下面是我旧代码:

        ConnectionConfig connectionConfig = ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE).setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Constant.DEFAULT_CHARSET).setMessageConstraints(messageConstraints).build();

下面是新代码:

ConnectionConfig connectionConfig = ConnectionConfig.custom()// 设置连接配置  
        .setConnectTimeout(Timeout.of(Duration.ofMillis(CONNECT_TIMEOUT))) // 设置连接超时  
        .setSocketTimeout(Timeout.of(Duration.ofMillis(SOCKET_TIMEOUT))) // 设置 socket 超时  
        .setTimeToLive(Timeout.of(Duration.ofMillis(MAX_ACCEPT_TIME))) // 设置生存时间  
        .setValidateAfterInactivity(Timeout.of(Duration.ofMillis(MAX_ACCEPT_TIME))) // 设置在不活动之后验证  
        .build();

总体讲没有太大差异,后两个配置项对于性能测试来讲也不重要,毕竟连接资源还有连接管理器和异步的资源回收线程负责。

连接池管理器

旧代码:

// 采用绕过验证的方式处理https请求
        // 设置协议http和https对应的处理socket链接工厂的对象
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE)).build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, dnsResolver);
        // 消息约束
        MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(HttpClientConstant.MAX_HEADER_COUNT).setMaxLineLength(HttpClientConstant.MAX_LINE_LENGTH).build();

新代码依旧是取消了一些配置API,其中改动比较大就是创建API,虽然PoolingHttpClientConnectionManager重载构造方法非常多,但是顺序写死了,我只想设置连接配置和DNS解析器,如果用构造方法,必须使用一个N个参数的,非常不优雅。这里推荐builder来完成,我们来看build()方法源码:

        PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(RegistryBuilder.create().register(URIScheme.HTTP.id, PlainConnectionSocketFactory.getSocketFactory()).register(URIScheme.HTTPS.id, this.sslSocketFactory != null ? this.sslSocketFactory : (this.systemProperties ? SSLConnectionSocketFactory.getSystemSocketFactory() : SSLConnectionSocketFactory.getSocketFactory())).build(), this.poolConcurrencyPolicy, this.poolReusePolicy, (TimeValue)null, this.schemePortResolver, this.dnsResolver, this.connectionFactory);

默认是有HTTP的连接工厂类注册到连接池管理器中的,所以不用重复设置了,而且也没有预留设置HTTP的API。

异步连接池管理器大差不差,其中有一个TlsStrategy是同步管理器没有的,设置方法如下:

.setTlsStrategy(new BasicClientTlsStrategy(sslContext))

builder创建这次新的API用了create()方法,旧的API还是使用custom()。

请求配置

在请求配置中,依然取消了不少API,主要是跟连接怕这出重复的配置项,比较喜欢这种,同一个配置多处配置会导致额外的问题和排查成本,新代码如下:

private static RequestConfig getRequestConfig() {  
    return RequestConfig.custom().setConnectionRequestTimeout(Timeout.ofMilliseconds(CONNECT_REQUEST_TIMEOUT)).setCookieSpec("ignoreCookies").setRedirectsEnabled(false).build();  
}

这里有一个cookieSpec的设置比较尴尬,保留了API,却取消了配置项的枚举类,之后先用字符串代替一下,放迷路内容:

@Deprecated  
public static final String BROWSER_COMPATIBILITY = "compatibility";  
public static final String NETSCAPE = "netscape";  
public static final String STANDARD = "standard";  
public static final String STANDARD_STRICT = "standard-strict";  
/** @deprecated */  
@Deprecated  
public static final String BEST_MATCH = "best-match";  
public static final String DEFAULT = "default";  
public static final String IGNORE_COOKIES = "ignoreCookies";

在性能测试当中,不需要 CookieStore 来管理cookie,所以选择忽略。

创建HttpClient

我用到了一个新的API org.apache.hc.client5.http.impl.classic.HttpClientBuilder#disableCookieManagement 看源码文档,看着是取消 CookieStore 的配置,因为我两处都设计了,暂时没有发现异常。

拦截器

方法参数多了一个,旧代码:

            public void process(HttpResponse httpResponse, HttpContext httpContext)

新代码:

public void process(HttpResponse httpResponse, EntityDetails entityDetails, HttpContext httpContext)

资源回收

连接池管理器有两个可供调用的资源回收方法,通常会异步调用防止资源异常:

connManager.closeExpiredConnections();
connManager.closeIdleConnections(HttpClientConstant.IDLE_TIMEOUT, TimeUnit.SECONDS);

新代码如下:

connManager.closeExpired();  
connManager.closeIdle(TimeValue.ofSeconds(IDLE_TIMEOUT));

异步客户端

启动异步客户端的方法start()不变,但是源码中判断逻辑有些区别,特别是在状态属性上。旧代码:

public void start() {  
    if (this.status.compareAndSet(CloseableHttpAsyncClientBase.Status.INACTIVE, CloseableHttpAsyncClientBase.Status.ACTIVE) && this.reactorThread != null) {  
        this.reactorThread.start();  
    }  
  
}

新代码:

public final void start() {  
    if (this.status.compareAndSet(AbstractHttpAsyncClientBase.Status.READY, AbstractHttpAsyncClientBase.Status.RUNNING)) {  
        DefaultConnectingIOReactor var10001 = this.ioReactor;  
        this.executorService.execute(var10001::start);  
    }  
  
}

代理

在旧代码中,代理配置可以直接在HttpClient中设置,新代码将API设置为过时,需要在RequestConfig中设置才行,代码不变,如下:

setProxy(new HttpHost(ip, port))

请求、响应对象名称

启用了一大批classic开头的对象,例如 org.apache.hc.core5.http.message.BasicClassicHttpRequestorg.apache.hc.core5.http.ClassicHttpResponse ,而且各类封装号的HTTP请求对象的报名也变成了 org.apache.hc.client5.http.classic.methods 。看来这个版本要回归经典了。

实体接口

在旧版代码中,想要处理请求或者响应实体,必须是 org.apache.http.HttpEntityEnclosingRequest 对象,在新版代码中变成了 org.apache.hc.core5.http.HttpEntityContainer ,而且取消了 boolean expectContinue() 方法。

全员携带实体

在旧版代码中,GET和DELETE请求默认是不携带请求实体的,如果想实现该功能需要使用者自己实现,新版中,全员携带实体。这个改变还是很喜闻乐见的。

设置实体

设置实体的API也有少许变动,原来是设置String类型编码格式,现在直接设置 java.nio.charset.Charset ,真是一大进步。

获取header

方法名从 getAllHeader 变成了 getHeaders,别的没了。

响应行

HttpClient 5取消了 获取响应行的的API getStatusLine ,如果想获取状态码,请用:org.apache.hc.client5.http.impl.classic.CloseableHttpResponse#getCode ,个人感觉并不合适,这跟HTTP请求构成有点不一致,但是方便了倒是真的。

获取URI

旧版方法:getURI,返回URI对象,新版:getUri,也返回URI对象,还有一个 getRequestUri 返回String对象。就是大小写的差异,怀疑是不是为了适配代码自动补充的工具。

异步请求

在同步的HttpClient中也是支持异步请求的,旧版代码和同步请求公用请求对象,新版代码增加了新的请求对象:org.apache.hc.client5.http.async.methods.SimpleHttpRequest,这个类明白子类,也不继承于前文提到的 HttpUriRequestBase,感觉就是独立分支一样。同样的响应对象也是 org.apache.hc.client5.http.async.methods.SimpleHttpResponse

HttpClient 5中两者都提供了从同步对象拷贝的方法copy(),奇怪的是请求的拷贝被标记成了过时方法,迷惑行为。从源码中看到可以方便快捷创建GET和POST请求。

响应中有直接获取body的方法 org.apache.hc.client5.http.async.methods.SimpleHttpResponse#getBodyText,看了一下,不太好借鉴到同步方法中。

总结

一个字:折腾。API调用已经完活儿了,后期再根据测试结果分享其他方面的变更感受。

如果没有强需求,不建议升级 HttpClient 5。

标签:HttpClient5,HTTP,请求,--,代码,API,public,HttpClient
From: https://blog.51cto.com/FunTester/8970246

相关文章

  • sql语句一览表
    登录到MySQL:mysql-h主机名-u用户名-p-h:该命令用于指定客户端所要登录的MySQL主机名,登录当前机器该参数可以省略;-u:所要登录的用户名;-p:告诉服务器将会使用一个密码来登录,如果所要登录的用户名密码为空,可以忽略此选项。创建一个数据库:createdatabase数据库......
  • 如何在Go语言中处理反爬虫机制
    在当今互联网时代,网站的反爬虫机制变得越来越普遍。这些机制旨在保护网站的数据和资源,防止恶意爬虫对网站造成过大负荷。对于Go语言开发者来说,了解如何处理反爬虫机制是至关重要的。本文将介绍一些在Go语言中处理反爬虫机制的方法和技巧。1.使用合适的User-AgentUser-Agent是HTTP请......
  • 如何在Go语言中处理网站登录和会话保持问题
    在进行网页爬取时,有些网站可能要求用户登录后才能访问特定页面或获取数据。为了处理这种情况,我们需要在Go语言中模拟用户登录并保持会话。本文将介绍一些在Go语言中处理网站登录和会话保持的方法和技巧。1.理解网站登录流程在开始处理登录和会话保持之前,首先需要理解目标网站的登录......
  • Python 爬虫在数据分析方面有什么潜力
    在当今信息爆炸的时代,大量的数据被生成和存储,这给企业、学术界和个人提供了巨大的机会和挑战。爬虫作为一种数据获取的技术手段,可以帮助我们从互联网上获取大量的数据。结合数据分析技术,爬虫在数据分析方面具有巨大的潜力。本文将介绍一些爬虫在数据分析方面的潜力和应用场景。1.获......
  • 做到这几点,澳福3天的收益比得上3年的交易
    各位投资者不敢想象吧!澳福仅仅是做到这几点就找到了好的讲师,3天的收益就比之前3年的收益都高,下面澳福就把找讲师的具体几点和大家进行分享!一.明确目标,制定计划。在交易之前,需要明白你想要达到的目标,最终的结果。如果知道自己的目标,就会明白想从讲师课程中获得什么。是完整的课程......
  • 如何优化 HTTP 请求以提高网页加载速度
    在今天的高速互联网时代,网页加载速度对于用户体验和网站的成功至关重要。HTTP请求是网页加载过程中的关键环节之一。通过优化HTTP请求,我们可以显著提高网页的加载速度,从而提升用户体验和网站的竞争力。本文将介绍一些优化HTTP请求的技巧和策略。1.减少请求次数每个HTTP请求都会产生......
  • iOS苹果App应用程序上架后提示有三方登入是怎么回事?如何解决?
    Hello大家好!我是咕噜铁蛋!现在越来越多的App都提供了三方登陆功能,比如使用微信、QQ、微博等社交媒体账号登陆。但是,有些开发者在将App上架到苹果应用商店时,会遇到提示“您的应用程序使用了第三方登录”的问题。今天铁蛋将对这一问题进行探讨,并提供解决方法。一.什么是三方登陆?三......
  • python的任何题目开头加上一句class的语句就是面向对象程序设计吗
    Python的任何题目开头加上一句class的语句并不意味着是面向对象程序设计(Object-OrientedProgramming,OOP)。面向对象程序设计是一种编程范式,它将程序组织为对象的集合,每个对象都有自己的状态和行为,并且可以与其他对象进行交互。在Python中,使用class关键字可以定义类,类是对象的蓝图,描......
  • 2023年12月深圳CPDA数据分析师认证来这学习
    CPDA数据分析师认证是大数据方面的认证,助力数据分析人员打下扎实的数据分析基础知识功底,为入门数据分析保驾护航。帮助数据分析人员掌握系统化的数据分析思维和方法论,提升工作效率和决策能力,遇到问题能够举一反三,为大部分决策难题提供解决方案。帮助数据分析人员掌握几种通用的数据......
  • 2023年12月北京/南京/深圳软考高级信息系统项目管理师招生
    信息系统项目管理师是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目之一,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职称资格考试。信息系统项目管理师,属于软考三个级别中的“高级”。 【报考要求】 不设学历与资历条......