首先由于项目的需要,引入了HttpClient客户端来发向服务器发起Http请求,项目中使用到了2个httpclient的版本:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.8</version>
</dependency>
最开始没有太在意,后来发现这两个版本有一个大坑。通常使用HttpClient的时候,需要给HttpClient配置一些重要的参数,比如连接池等。具体看代码:
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(10*1000) //向下面连接池获取连接的超时时间
.setConnectTimeout(100*1000) //请求超时时间
.setSocketTimeout(60*1000).build(); //设置数据读取超时时间
//请求连接池
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
//设置每个路由最大连接数,这里的路由可以理解为是服务器主机名称
poolingConnectionManager.setDefaultMaxPerRoute(50);
//设置整个连接池的总大小,上面的路由连接数不会超过整个连接池总大小
poolingConnectionManager.setMaxTotal(100);
//下面是创建client客户端
CloseableHttpClient client = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(poolingConnectionManager)
.setKeepAliveStrategy(connectionKeepAliveStrategy())
.build();
//向某个url发起http请求
HttpGet get = new HttpGet(url);
client.execute(get);
在4.5.8版本中如果对client设置了这些参数的话,那么创建的每一个HttpGet都会获取到对client的设置的这些参数信息。如果使用4.5版本,那么对client设置这些参数,对上面代码创建的get请求是<font color=red size=5>无效的,记住无效</font>,需要在执行client.execute(get)之前配置信息加入到get中:
HttpGet get = new HttpGet(url);
get.setConfig(requestConfig);
client.execute(get);
具体原因见源码,在org.apache.http.impl.client.InternalHttpClient类中:下面是4.5版本
protected CloseableHttpResponse doExecute(
...
RequestConfig config = null;
if (request instanceof Configurable) {
config = ((Configurable) request).getConfig();
}
if (config == null) {
final HttpParams params = request.getParams();
if (params instanceof HttpParamsNames) {
if (!((HttpParamsNames) params).getNames().isEmpty()) {
config = HttpClientParamConfig.getRequestConfig(params);
}
} else {
config = HttpClientParamConfig.getRequestConfig(params);
}
}
...
下面是4.5.8版本的源码
protected CloseableHttpResponse doExecute(
...
RequestConfig config = null;
if (request instanceof Configurable) {
config = ((Configurable) request).getConfig();
}
if (config == null) {
final HttpParams params = request.getParams();
if (params instanceof HttpParamsNames) {
if (!((HttpParamsNames) params).getNames().isEmpty()) {
//关键代码,4.5.8把this.defaultConfig赋值给了每一个创建的Http请求方法
config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig);
}
} else {
config = HttpClientParamConfig.getRequestConfig(params, this.defaultConfig);
}
}
...
因此大家在以后选择client版本的,如果选择了的是4.5版本那么一定要注意需要把相关设置的配置加到每一个http请求方法上面。
网友评论