package com.loong.eshop.cache.ha.http;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Map;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
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.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import com.alibaba.fastjson.JSON;
public class WebTools {
private static Logger logger = LoggerFactory.getLogger(WebTools.class);
/**读取超时 */
private final static int SOCKET_TIMEOUT = 40000;
/**连接超时 */
private final static int CONNECTION_TIMEOUT = 40000;
/**每个HOST的最大连接数量 */
//private final static int MAX_CONN_PRE_HOST = 2;
/**连接池的最大连接数 */
private final static int MAX_CONN = 200;
/**每个路由的最大连接数 */
private final static int MAX_PRE_ROUTE = 100;
/**重试了连接次数 */
private final static int EXECUTION_COUNT = 5;
/**连接池管理 */
private final static PoolingHttpClientConnectionManager POOL_CONN_MANAGER = new PoolingHttpClientConnectionManager();
/**
* retry handler
*/
private final static HttpRequestRetryHandler HTTP_REQUEST_RETRY_HANDLER = new HttpRequestRetryHandler(){
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
// 如果已经重试了n次,就放弃
if(executionCount >= EXECUTION_COUNT){return false;}
// 如果服务器丢掉了连接,那么就重试
if(exception instanceof NoHttpResponseException){return true;}
// 不要重试SSL握手异常
if(exception instanceof SSLHandshakeException){return false;}
// 超时
if(exception instanceof InterruptedIOException){return false;}
// 目标服务器不可达
if(exception instanceof UnknownHostException){return true;}
// 连接被拒绝
if(exception instanceof ConnectTimeoutException){return false;}
// SSL握手异常
if(exception instanceof SSLException){return false;}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
// 如果请求是幂等的,就再次尝试
if(!(request instanceof HttpEntityEnclosingRequest)){
return true;
}
return false;
}
};
static {
// 类加载的时候,设置最大连接 和 每个路由的最大连接数
POOL_CONN_MANAGER.setMaxTotal(MAX_CONN);
POOL_CONN_MANAGER.setDefaultMaxPerRoute(MAX_PRE_ROUTE);
}
/**
* api code
*/
private static CloseableHttpClient getCloseableHttpClient(){
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(POOL_CONN_MANAGER)
.setRetryHandler(HTTP_REQUEST_RETRY_HANDLER)
.build();
return httpClient;
}
public static RequestConfig getRequestConfig(){
//HttpHost proxy = new HttpHost("代理IP", 8080, "HTTP");//代理
RequestConfig requestConfig = RequestConfig.custom()
//.setProxy(proxy)
//是设置连接到目标 URL 的等待时长,超过这个时间还没连上就抛出连接超时;
.setConnectTimeout(CONNECTION_TIMEOUT)
//是连接到目标URL 之后等待返回响应的时长 ,即超过这个时间就放弃本次调用并抛出
.setSocketTimeout(SOCKET_TIMEOUT)
//.setConnectionRequestTimeout(60000)//从连接池获取连接的timeout
//自动重定向关闭
.setRedirectsEnabled(false)
.build();
return requestConfig;
}
/**
* post请求
* @param url
* @param json
* @param interfaceName
* @return
*/
public static String doPostJson(String url, String json, String interfaceName){
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName()+" ";
Map<String, Object> result = null;
String resultString = "";
//创建Httpclient对象
CloseableHttpClient httpClient = getCloseableHttpClient();
//创建Http Post请求
HttpPost httpPost = new HttpPost();
CloseableHttpResponse response = null;
try {
httpPost.addHeader("Content-Type", "application/json; charset=UTF-8");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Accept-Encoding", "gzip");
httpPost.addHeader("Content-Encoding", "UTF-8");
httpPost.setConfig(getRequestConfig());
//创建请求内容
StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(stringEntity);
//执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
if(response.getStatusLine().getStatusCode() == HttpServletResponse.SC_OK){
Map<String, Object> map = JSON.parseObject(resultString, Map.class);
}
return "成功";
} catch (SocketTimeoutException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (ConnectTimeoutException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (HttpHostConnectException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (Exception e) {
logger.error("调用接口异常", e);
return "失败";
}finally{
if(null != response){
try {
EntityUtils.consume(response.getEntity());
response.close();
} catch (Exception e2) {
logger.error("调用接口关闭异常", e2);
}
}
}
}
public static String doGet(String url, Map<String, String> params, String interfaceName){
String methodName = Thread.currentThread().getStackTrace()[1].getMethodName()+" ";
Map<String, Object> result = null;
String resultString = "";
//创建Httpclient对象
CloseableHttpClient httpClient = getCloseableHttpClient();
CloseableHttpResponse response = null;
try {
URIBuilder b = new URIBuilder(url);
if(!CollectionUtils.isEmpty(params)){
params.entrySet().forEach(entry -> {
b.addParameter(entry.getKey(), entry.getValue());
});
}
URI urlPath = b.build();
//创建Http Get请求
HttpGet httpGet = new HttpGet(urlPath);
httpGet.addHeader("Content-Type", "application/json; charset=UTF-8");
httpGet.addHeader("Accept", "application/json");
httpGet.addHeader("Accept-Encoding", "gzip");
httpGet.addHeader("Content-Encoding", "UTF-8");
httpGet.setConfig(getRequestConfig());
//执行http请求
response = httpClient.execute(httpGet);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
if(response.getStatusLine().getStatusCode() == HttpServletResponse.SC_OK){
Map<String, Object> map = JSON.parseObject(resultString, Map.class);
}
return "成功";
} catch (SocketTimeoutException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (ConnectTimeoutException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (HttpHostConnectException e) {
logger.error("调用接口超时", e);
return "失败";
} catch (Exception e) {
logger.error("调用接口异常", e);
return "失败";
}finally{
if(null != response){
try {
EntityUtils.consume(response.getEntity());
response.close();
} catch (Exception e2) {
logger.error("调用接口关闭异常", e2);
}
}
}
}
}