HttpClient 使用连接池 Pool 构建链接(兼容HTTPS)
Posted OkidoGreen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HttpClient 使用连接池 Pool 构建链接(兼容HTTPS)相关的知识,希望对你有一定的参考价值。
HttpClient 每次使用后到底需不需要 close,特别是在使用连接池的情况下
What is the difference between CloseableHttpClient and HttpClient in Apache HttpClient API?
The other answers don't seem to address why close()
is really necessary? * 2
Doubt on the answer "HttpClient resource deallocation".
It is mentioned in old 3.x httpcomponents doc, which is long back and has a lot difference from 4.x HC. Besides the explanation is so brief that doesn't say what this underlying resource is.
I did some research on 4.5.2 release source code, found the implementations of CloseableHttpClient:close()
basically only closes its connection manager.
(FYI) That's why when you use a shared PoolingClientConnectionManager
and call client close()
, exception java.lang.IllegalStateException: Connection pool shut down
will occur. To avoid, setConnectionManagerShared
works.
I prefer not do CloseableHttpClient:close()
after every single request
I used to create a new http client instance when doing request and finally close it. In this case, it'd better not to call close()
. Since, if connection manager doesn't have "shared" flag, it'll be shutdown, which is too expensive for a single request.
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created by Administrator on 2018/05/09.
*/
public class HttpClientUtil
private static HttpClientContext context = HttpClientContext.create();
private static RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200).setSocketTimeout(500)
.setConnectionRequestTimeout(200).setCookieSpec(CookieSpecs.STANDARD_STRICT).
setExpectContinueEnabled(true).
setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST)).
setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
//https
private static SSLConnectionSocketFactory socketFactory;
private static TrustManager manager = new X509TrustManager()
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
@Override
public X509Certificate[] getAcceptedIssuers()
return null;
;
private static void enableSSL()
try
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]manager, null);
socketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
catch (NoSuchAlgorithmException e)
e.printStackTrace();
catch (KeyManagementException e)
e.printStackTrace();
private static HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler()
@Override
public boolean retryRequest(IOException exception,
int executionCount, HttpContext context)
return false;
;
static
enableSSL();
private static Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
private static PoolingHttpClientConnectionManager pccm = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
static
pccm.setMaxTotal(100); // 连接池最大并发连接数
pccm.setDefaultMaxPerRoute(20); // 单路由最大并发数
private static HttpClientBuilder clientBuilder = HttpClients.custom().setConnectionManager(pccm).
setConnectionManagerShared(true).setRetryHandler(myRetryHandler)
.setDefaultRequestConfig(requestConfig);
/**
* https get
* @param url
* @param data
* @return
* @throws IOException
*/
public static CloseableHttpResponse doGet(String url, String data)
CloseableHttpClient httpClient = clientBuilder.build();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = null;
try
response = httpClient.execute(httpGet, context);
catch (Exception e)
e.printStackTrace();
return response;
/**
* https/http post
* @param url
* @param values
* @return
* @throws IOException
*/
public static CloseableHttpResponse doPost(String url, List<NameValuePair> values)
CloseableHttpClient httpClient = clientBuilder.build();
HttpPost httpPost = new HttpPost(url);
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(values, Consts.UTF_8);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
try
response = httpClient.execute(httpPost, context);
catch (Exception e)
return response;
public static CloseableHttpResponse doJsonPost(String url,String json)
CloseableHttpClient httpClient = clientBuilder.build();
HttpPost httpPost = new HttpPost(url);
CloseableHttpResponse httpResponse;
httpPost.addHeader(HTTP.CONTENT_TYPE, "application/json");
httpPost.addHeader("charset", "utf-8");
CloseableHttpResponse response = null;
try
response = httpClient.execute(httpPost, context);
catch (Exception e)
return response;
/**
* 直接把Response内的Entity内容转换成String
*
* @param httpResponse
* @return
*/
public static String toString(CloseableHttpResponse httpResponse)
if(httpResponse == null) return null;
// 获取响应消息实体
String result = null;
try
HttpEntity entity = httpResponse.getEntity();
if (entity != null)
result = EntityUtils.toString(entity,"UTF-8");
catch (Exception e)finally
try
httpResponse.close();
catch (IOException e)
e.printStackTrace();
return result;
public static void main(String[] args)
CloseableHttpResponse response = HttpClientUtil.doGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wxb2ebe42765aad029&secret=720661590f720b1f501ab3f390f80d52","");
System.out.println(HttpClientUtil.toString(response));
response = HttpClientUtil.doPost("http://www.baidu.com/cgi-bin/token?grant_type=client_credential&appid=wxb2ebe42765aad029&secret=720661590f720b1f501ab3f390f80d52",
new ArrayList<NameValuePair>());
System.out.println(HttpClientUtil.toString(response));
以上是关于HttpClient 使用连接池 Pool 构建链接(兼容HTTPS)的主要内容,如果未能解决你的问题,请参考以下文章