public classHttpClientUtils {private final static Logger logger = Logger.getLogger(HttpClientUtils.class);private staticCloseableHttpClient httpClient;private static PoolingHttpClientConnectionManager manager; //连接池管理类
private static ScheduledExecutorService monitorExecutor; //监控
private final static Object syncLock = new Object(); //相当于线程锁,用于线程安全
private static final int CONNECT_TIMEOUT = HttpClientConfig.getHttpConnectTimeout();//设置连接建立的超时时间为10s
private static final int SOCKET_TIMEOUT =HttpClientConfig.getHttpSocketTimeout();private static final int MAX_CONN = HttpClientConfig.getHttpMaxPoolSize(); //最大连接数
private static final int Max_PRE_ROUTE =HttpClientConfig.getHttpMaxPoolSize();private static final int MAX_ROUTE =HttpClientConfig.getHttpMaxPoolSize();/*** 对http请求进行基本设置
*
*@paramhttpRequestBase
* http请求*/
private static voidsetRequestConfig(HttpRequestBase httpRequestBase) {
RequestConfig requestConfig=RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
httpRequestBase.setConfig(requestConfig);
}public staticCloseableHttpClient getHttpClient(String url) {
String hostName= url.split("/")[2];//System.out.println(hostName);
int port = 80;if (hostName.contains(":")) {
String[] args= hostName.split(":");
hostName= args[0];
port= Integer.parseInt(args[1]);
}if (httpClient == null) {//多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁
synchronized(syncLock) {if (httpClient == null) {
httpClient=createHttpClient(hostName, port);//开启监控线程,对异常和空闲线程进行关闭
monitorExecutor = Executors.newScheduledThreadPool(1);
monitorExecutor.scheduleAtFixedRate(newTimerTask() {
@Overridepublic voidrun() {//关闭异常连接
manager.closeExpiredConnections();//关闭5s空闲的连接
manager.closeIdleConnections(HttpClientConfig.getHttpIdelTimeout(), TimeUnit.MILLISECONDS);
logger.debug("close expired and idle for over 5s connection");
}
}, HttpClientConfig.getHttpMonitorInterval(), HttpClientConfig.getHttpMonitorInterval(),
TimeUnit.MILLISECONDS);
}
}
}returnhttpClient;
}/*** 根据host和port构建httpclient实例
*
*@paramhost
* 要访问的域名
*@paramport
* 要访问的端口
*@return
*/
public static CloseableHttpClient createHttpClient(String host, intport) {
ConnectionSocketFactory plainSocketFactory=PlainConnectionSocketFactory.getSocketFactory();
LayeredConnectionSocketFactory sslSocketFactory=SSLConnectionSocketFactory.getSocketFactory();
Registry registry = RegistryBuilder.create()
.register("http", plainSocketFactory).register("https", sslSocketFactory).build();
manager= newPoolingHttpClientConnectionManager(registry);//设置连接参数
manager.setMaxTotal(MAX_CONN); //最大连接数
manager.setDefaultMaxPerRoute(Max_PRE_ROUTE); //路由最大连接数
HttpHost httpHost = newHttpHost(host, port);
manager.setMaxPerRoute(newHttpRoute(httpHost), MAX_ROUTE);//请求失败时,进行请求重试
HttpRequestRetryHandler handler = newHttpRequestRetryHandler() {
@Overridepublic boolean retryRequest(IOException e, inti, HttpContext httpContext) {if (i > 3) {//重试超过3次,放弃请求
logger.error("retry has more than 3 time, give up request");return false;
}if (e instanceofNoHttpResponseException) {//服务器没有响应,可能是服务器断开了连接,应该重试
logger.error("receive no response from server, retry");return true;
}if (e instanceofSSLHandshakeException) {//SSL握手异常
logger.error("SSL hand shake exception");return false;
}if (e instanceofInterruptedIOException) {//超时
logger.error("InterruptedIOException");return false;
}if (e instanceofUnknownHostException) {//服务器不可达
logger.error("server host unknown");return false;
}if (e instanceofConnectTimeoutException) {//连接超时
logger.error("Connection Time out");return false;
}if (e instanceofSSLException) {
logger.error("SSLException");return false;
}
HttpClientContext context=HttpClientContext.adapt(httpContext);
HttpRequest request=context.getRequest();if (!(request instanceofHttpEntityEnclosingRequest)) {//如果请求不是关闭连接的请求
return true;
}return false;
}
};
CloseableHttpClient client=HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler)
.build();returnclient;
}/*** 关闭连接池*/
public static voidcloseConnectionPool() {try{
httpClient.close();
manager.close();
monitorExecutor.shutdown();
}catch(IOException e) {
e.printStackTrace();
}
}
}