import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.io.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
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.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpConnectionFactory;
import org.apache.http.conn.ManagedHttpClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import com.forms.cmap.common.base.Constants;
public class HttpClientUtils3 {
private static Logger log = LoggerFactory.getLogger("tlog");
public static final int READBUFFERSIZE = 65536;
public static final int CONNECT_TIMEOUT = 20000;// 连接超时时间 单位:毫秒
public static final int SO_TIMEOUT = 50000;// 读取超时时间 单位:毫秒
private static final int maxTotal = 256;// 设置整个连接池最大连接数
private static final int defaultMaxPerRoute = 64;// 单个路由最大连接数
private static PoolingHttpClientConnectionManager poolConnManager = null;// 池化管理
private static CloseableHttpClient httpClient;
private static CloseableHttpClient sslHttpClient;
private static RequestConfig requestConfig;// 请求器的配置
//public static synchronized CloseableHttpClient getHttpClient(){
static {
if(httpClient == null||sslHttpClient== null){
//注册访问协议相关的Socket工厂
Registry
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
.build();
//System.out.println("初始化池化连接管理器");
//HttpConnection 工厂:配置写请求/解析响应处理器
HttpConnectionFactory
= new ManagedHttpClientConnectionFactory(DefaultHttpRequestWriterFactory.INSTANCE,
DefaultHttpResponseParserFactory.INSTANCE);
//DNS 解析器
DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
//创建池化连接管理器
poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry,connectionFactory,dnsResolver);
//默认为Socket配置
SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
poolConnManager.setDefaultSocketConfig(defaultSocketConfig);
poolConnManager.setMaxTotal(maxTotal); //设置整个连接池的最大连接数
//每个路由的默认最大连接,每个路由实际最大连接数由DefaultMaxPerRoute控制,而MaxTotal是整个池子的最大数
//设置过小无法支持大并发(ConnectionPoolTimeoutException) Timeout waiting for connection from pool
poolConnManager.setDefaultMaxPerRoute(defaultMaxPerRoute);//每个路由的最大连接数
//在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证,默认为2s
poolConnManager.setValidateAfterInactivity(5*1000);
//默认请求配置
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setConnectTimeout(2*1000) //设置连接超时时间,2s
.setSocketTimeout(5*1000) //设置等待数据超时时间,5s
.setConnectionRequestTimeout(2000) //设置从连接池获取连接的等待超时时间
.build();
//创建HttpClient
httpClient = HttpClients.custom()
.setConnectionManager(poolConnManager)
.setConnectionManagerShared(false) //连接池不是共享模式
.evictIdleConnections(60, TimeUnit.SECONDS) //定期回收空闲连接
.evictExpiredConnections()// 定期回收过期连接
.setConnectionTimeToLive(60, TimeUnit.SECONDS) //连接存活时间,如果不设置,则根据长连接信息决定
.setDefaultRequestConfig(defaultRequestConfig) //设置默认请求配置
.setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE) //连接重用策略,即是否能keepAlive
.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE) //长连接配置,即获取长连接生产多长时间
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)) //设置重试次数,默认是3次,当前是禁用掉(根据需要开启)
.build();
//System.out.println("初始化httpClient");
try {
sslHttpClient=getSSLHttpClient();
//System.out.println("初始化sslHttpClient");
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//定期回收空闲连接
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
//System.out.println("定期回收空闲连接");
poolConnManager.closeExpiredConnections();
poolConnManager.closeIdleConnections(60, TimeUnit.SECONDS);
/* if (poolConnManager != null && poolConnManager.getTotalStats() != null) {
System.out.println("now client pool " + poolConnManager.getTotalStats().toString());
}*/
}
}, 0, 5 * 1000);
//JVM 停止或重启时,关闭连接池释放掉连接(跟数据库连接池类似)
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
try{
if(httpClient !=null){
httpClient.close();
}
//System.out.println("JVM 停止或重启时,关闭连接池释放掉连接");
}catch(IOException e){
//System.out.println("error when close httpClient:"+e);
}
}
});
}
//return httpClient;
}
public static String post(String uri) throws Exception {
return postSSL(uri, null);
}
public static String post(String uri, String requestJson) throws Exception {
String result = "";
log.info("post requestJson:" + requestJson);
HttpResponse response = null;
HttpPost httpPost = new HttpPost(uri);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
.setConnectionRequestTimeout(CONNECT_TIMEOUT).setSocketTimeout(SO_TIMEOUT).build();
httpPost.setConfig(requestConfig);
if (StringUtils.isNotBlank(requestJson)) {
httpPost.setEntity(new StringEntity(requestJson, Charsets.UTF_8));
}
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
String loggerChainId = MDC.get(Constants.LOGGER_CHAIN_ID);
// 填充数据
if (StringUtils.isNotEmpty(loggerChainId)) {
httpPost.setHeader("Logger-Chain-Id", loggerChainId);
}
response = httpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null)
result = EntityUtils.toString(httpEntity);
return result;
}
public static String postSSL(String uri) throws Exception {
return postSSL(uri, null);
}
public static String postSSL(String uri, String data) throws Exception {
String result = "";
CloseableHttpResponse response = null;
try {
HttpPost httpPost = new HttpPost(uri);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
.setConnectionRequestTimeout(CONNECT_TIMEOUT).setSocketTimeout(SO_TIMEOUT).build();
httpPost.setConfig(requestConfig);
if (StringUtils.isNotBlank(data)) {
httpPost.setEntity(new StringEntity(data, Charsets.UTF_8));
}
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
String loggerChainId = MDC.get(Constants.LOGGER_CHAIN_ID);
// 填充数据
if (StringUtils.isNotEmpty(loggerChainId)) {
httpPost.setHeader("Logger-Chain-Id", loggerChainId);
}
response = sslHttpClient.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null)
result = EntityUtils.toString(httpEntity);
} finally {
if (response != null)
response.close();
/*if (httpclient != null)
httpclient.close();*/
}
return result;
}
private static CloseableHttpClient getSSLHttpClient() throws Exception {
CloseableHttpClient httpclient;
X509TrustManager trustManager = new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
};
SSLContext sc = SSLContext.getInstance(SSLConnectionSocketFactory.SSL);
sc.init(null, new TrustManager[] { trustManager }, new SecureRandom());
SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sc,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//httpclient = HttpClients.custom().setSSLSocketFactory(factory).build();
httpclient = HttpClients.custom().setConnectionManager(poolConnManager).setSSLSocketFactory(factory)
.setDefaultRequestConfig(requestConfig) // 默认请求配置
.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();
return httpclient;
}
public static String getSSL(String uri) throws Exception {
String result = "";
CloseableHttpResponse response = null;
try {
HttpGet httpget = new HttpGet(uri);
response = sslHttpClient.execute(httpget);
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null) {
result = EntityUtils.toString(httpEntity);
}
} finally {
if (response != null)
response.close();
/*if (httpclient != null)
httpclient.close();*/
}
return result;
}
public static CloseableHttpClient getHttpClient() throws Exception {
if(httpClient== null) {
CloseableHttpClient httpclient = HttpClients.createDefault();
return httpclient;
}else {
return httpClient;
}
}
}