使用版本如下:
<!-- HTTP Client -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-cache</artifactId>
<version>4.5.10</version>
<optional>true</optional>
</dependency>
CloseableHttpClient 基本实现代码如下:
@Slf4j
public class PoolingHttpClient {
private static PoolingHttpClientConnectionManager poolConnManager = null;
private static CloseableHttpClient defaultHttpClient;
//请求器的配置
private static RequestConfig requestConfig;
static {
try {
log.info("初始化HttpClient开始");
SSLContextBuilder builder = new SSLContextBuilder();
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
builder.build());
// 配置同时支持 HTTP 和 HTPPS
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register(
"http", PlainConnectionSocketFactory.getSocketFactory()).register(
"https", sslsf).build();
// 初始化连接管理器
poolConnManager = new PoolingHttpClientConnectionManager(
socketFactoryRegistry);
// 将最大连接数增加到200
poolConnManager.setMaxTotal(200);
// 设置最大路由[ 设置每个路由基础的连接],该值默认为2,并发比较差
poolConnManager.setDefaultMaxPerRoute(20);
// 根据默认超时限制初始化requestConfig
int socketTimeout = 10000;
int connectTimeout = 10000;
int connectionRequestTimeout = 10000;
requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(
connectTimeout).build();
// 初始化httpClient
defaultHttpClient = getConnection();
log.info("初始化HttpClient结束");
} catch (Exception e) {
log.error("初始化HttpClient失败");
}
}
public static CloseableHttpClient getConnection() {
CloseableHttpClient httpClient = HttpClients.custom()
// 设置连接池管理
.setConnectionManager(poolConnManager)
// 设置请求配置
.setDefaultRequestConfig(requestConfig)
// 设置重试次数
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
.build();
if (poolConnManager != null && poolConnManager.getTotalStats() != null) {
System.out.println("now client pool "
+ poolConnManager.getTotalStats().toString());
}
return httpClient;
}
}
CloseableHttpClient 关闭流的操作
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
1:httpResponse.close();
直接把连接放回连接池,而不是关闭连接
2:
finally {
EntityUtils.consume(httpEntity);
}
EntityUtils.consume 代码内部有进行关闭流的代码
public static void consume(HttpEntity entity) throws IOException {
if (entity != null) {
if (entity.isStreaming()) {
InputStream instream = entity.getContent();
if (instream != null) {
instream.close();
}
}
}
}
3: httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
InputStream is = httpEntity.getContent();
try {
//做一些操作
} finally {
//最后别忘了关闭应该关闭的资源,适当的释放资源
if (is != null) {
is.close();//此处也可以EntityUtils.consume(entity);
}
}
}
相当于自己实现了EntityUtils.consume内部的处理
4:String res = EntityUtils.toString(httpEntity, "UTF-8");
EntityUtils 内部 toString 方法有进行关流的操作:instream.close();
private static String toString(HttpEntity entity, ContentType contentType) throws IOException {
InputStream instream = entity.getContent();
if (instream == null) {
return null;
} else {
try {
Args.check(entity.getContentLength() <= 2147483647L, "HTTP entity too large to be buffered in memory");
int i = (int)entity.getContentLength();
if (i < 0) {
i = 4096;
}
Charset charset = null;
if (contentType != null) {
charset = contentType.getCharset();
if (charset == null) {
ContentType defaultContentType = ContentType.getByMimeType(contentType.getMimeType());
charset = defaultContentType != null ? defaultContentType.getCharset() : null;
}
}
if (charset == null) {
charset = HTTP.DEF_CONTENT_CHARSET;
}
Reader reader = new InputStreamReader(instream, charset);
CharArrayBuffer buffer = new CharArrayBuffer(i);
char[] tmp = new char[1024];
int l;
while((l = reader.read(tmp)) != -1) {
buffer.append(tmp, 0, l);
}
String var9 = buffer.toString();
return var9;
} finally {
instream.close();
}
}
}
CloseableHttpClient post调用具体代码:
public static String doPost(CloseableHttpClient httpClient, String url, String data, String logAction) throws Exception {
LocalDateTime startDate = LocalDateTime.now();
CloseableHttpResponse httpResponse = null;
HttpEntity httpEntity = null;
try {
long startTime = System.currentTimeMillis();
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(8 * 1000).setConnectTimeout(6 * 1000).build();
httpPost.setConfig(requestConfig);
StringEntity postEntity = new StringEntity(data, "UTF-8");
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpPost.setEntity(postEntity);
httpResponse = httpClient.execute(httpPost);
httpEntity = httpResponse.getEntity();
LocalDateTime endDate = LocalDateTime.now();
final long cost = System.currentTimeMillis() - startTime;
log.info((StringUtils.isNotBlank(logAction) ? logAction : "接口调用") + "请求耗时:{},发起时间:{},结束时间:{},请求数据:{}", cost, startDate, endDate, data);
String res = EntityUtils.toString(httpEntity, "UTF-8");
return res;
} catch (Exception ex) {
throw ex;
} finally {
// if (null != httpResponse) httpResponse.close();
EntityUtils.consume(httpEntity);
}
}
RequestConfig配置看如下链接:
ConnectTimeout、ConnectionRequestTimeout、SocketTimeout的含义_connect timeot_小咖张的博客-CSDN博客