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)); } }