package com.app.mvc.util;
import com.app.mvc.common.ThreadPool;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.scheme.Scheme;
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.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.UnsupportedEncodingException;
import java.nio.charset.CodingErrorAction;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
/**
* Created by jimin on 16/5/5.
*/
@Slf4j
public class HttpUtil {
/**
* 默认连接超时时间
*/
private static final int DEFAULT_CONNECT_TIMEOUT = 5000;
/**
* 默认读取超时时间
*/
private static final int DEFAULT_SOCKET_TIMEOUT = 60000;
/**
* 默认读取超时时间
*/
private static final int DEFAULT_CONN_REQUEST_TIMEOUT = 5000;
/**
* 最大连接数
*/
private static final int DEFAULT_MAX_CONN_TOTAL = 200;
/**
* 每个host最大连接数
*/
private static final int DEFAULT_MAX_CONN_PER_ROUTE = 20;
/**
* 使用缺省配置生成httpClient
*
* @return
*/
public static HttpClient defaultClient() {
return HttpClients.custom().setConnectionManager(getPoolingClientConnectionManager())
.setDefaultRequestConfig(getRequestConfig(DEFAULT_CONNECT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT, DEFAULT_CONN_REQUEST_TIMEOUT))
.setMaxConnTotal(DEFAULT_MAX_CONN_TOTAL).setMaxConnPerRoute(DEFAULT_MAX_CONN_PER_ROUTE).build();
}
/**
* 缺省connectionManager
*
* @return
*/
public static PoolingHttpClientConnectionManager getPoolingClientConnectionManager() {
try {
SSLContext sslContext = SSLContexts.custom().useTLS().build();
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} }, null);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE).register("https", new SSLConnectionSocketFactory(sslContext)).build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
connManager.setDefaultSocketConfig(socketConfig);
ConnectionConfig connectionConfig = ConnectionConfig.custom().setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8).build();
connManager.setDefaultConnectionConfig(connectionConfig);
return connManager;
} catch (Exception e) {
log.error("build client connection manager failed", e);
throw new RuntimeException(e);
}
}
/**
* 生成requestConfig
*
* @param connectTimeout 请求超时
* @param socketTimeout 接口响应超时
* @param connectionRequestTimeout 获取连接超时
* @return
*/
public static RequestConfig getRequestConfig(int connectTimeout, int socketTimeout, int connectionRequestTimeout) {
return RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout).setConnectTimeout(connectTimeout).setSocketTimeout(socketTimeout)
.build();
}
/**
* post请求
*
* @param reqURL
* @param params
* @return
*/
public static String executePOST(HttpClient client, String reqURL, Map<String, String> params, final int retryTimes, HttpClientContext context)
throws Exception {
HttpPost httpPost = new HttpPost(reqURL);
List<NameValuePair> reqParams = buildPostParams(params);
httpPost.setEntity(new UrlEncodedFormEntity(reqParams, "utf-8"));
return executePOST(client, httpPost, retryTimes, context);
}
/**
* 执行post请求
*
* @param client 指定使用的client
* @param httpPost 调用者给出post实例,进行header、cookie等设定
* @param retryTimes 失败重试次数,需调用者给出
* @return
* @throws Exception
*/
public static String executePOST(HttpClient client, HttpPost httpPost, final int retryTimes, HttpClientContext context) throws Exception {
String responseText = StringUtils.EMPTY;
for (int i = 0; i < retryTimes; i++) {
HttpEntity resEntity = null;
try {
HttpResponse response = client.execute(httpPost, context);
resEntity = response.getEntity();
StatusLine status = response.getStatusLine();
if (status != null && status.getStatusCode() == 200) {
responseText = EntityUtils.toString(resEntity, "utf-8");
} else {
log.error("httpPost请求响应状态异常, url:{}, responseStatus:{}", httpPost.getURI(), status);
throw new HttpException(String.format("请求响应状态异常!状态码=%s,url=%s", status, httpPost.getURI()));
}
} catch (Exception e) {
log.error("httpPost请求异常, url:{}, errmsg:{}", httpPost.getURI(), e.getMessage(), e);
if (i == retryTimes) {
throw e;
}
} finally {
httpPost.releaseConnection();
EntityUtils.consume(resEntity);
}
}
return responseText;
}
/**
* get请求
*
* @param client
* @param reqURL
* @param retryTimes
* @return
* @throws Exception
*/
public static String executeGet(HttpClient client, String reqURL, final int retryTimes, HttpClientContext context) throws Exception {
HttpGet httpGet = new HttpGet(reqURL);
return executeGet(client, httpGet, retryTimes, context);
}
/**
* 执行get请求
*
* @param client 指定client
* @param retryTimes
* @return
* @throws Exception
*/
public static String executeGet(HttpClient client, HttpGet httpGet, final int retryTimes, HttpClientContext context) throws Exception {
String responseText = StringUtils.EMPTY;
for (int i = 0; i < retryTimes; i++) {
HttpEntity resEntity = null;
try {
HttpResponse response = client.execute(httpGet, context);
resEntity = response.getEntity();
StatusLine status = response.getStatusLine();
if (status != null && status.getStatusCode() == 200) {
responseText = EntityUtils.toString(resEntity, "utf-8");
} else {
log.error("httpGet请求响应状态异常, url:{}, responseStatus:{}", httpGet.getURI().toURL(), status);
throw new HttpException(String.format("请求响应状态异常!状态码=%s,url=%s", status, httpGet.getURI().toURL()));
}
} catch (Exception e) {
log.error("httpGet请求异常, url:{}, errmsg:{}", httpGet.getURI().toURL(), e.getMessage(), e);
if (i == retryTimes) {
throw e;
}
} finally {
httpGet.releaseConnection();
EntityUtils.consume(resEntity);
}
}
return responseText;
}
public static List<NameValuePair> buildPostParams(Map<String, String> reqParams) {
List<NameValuePair> params = Lists.newArrayList();
for (Entry<String, String> param : reqParams.entrySet()) {
params.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
return params;
}
/**
* 根据URL 组装 HTTP POST
*
* @param url
* @param json
* @return
* @throws UnsupportedEncodingException
*/
public static HttpPost getPost(String url, String json) throws UnsupportedEncodingException {
HttpPost httpPost = new HttpPost(url);
StringEntity stringEntity = new StringEntity(json, "utf-8");
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
httpPost.setHeader(new BasicHeader("Accept", "application/json"));
return httpPost;
}
/**
* 使用post请求获取url内容(HTTPS)
*
* @param httpPost 请求地址
* @param connectTimeout 连接超时时间
* @param socketTimeout 读取超时时间
*/
public static String getPostSSLContent(HttpPost httpPost, int connectTimeout, int socketTimeout) throws Exception {
return process(httpPost, connectTimeout, socketTimeout, true);
}
private static String process(final HttpRequestBase httpUriRequest, int connectTimeout, int socketTimeout, boolean isSSL) throws Exception {
final DefaultHttpClient client = getClient(connectTimeout, socketTimeout, isSSL);
FutureTask<String> fu = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
String resultString = "";
HttpResponse response = client.execute(httpUriRequest);
HttpEntity entity = null;
try {
entity = response.getEntity();
StatusLine status = response.getStatusLine();
if (status != null && status.getStatusCode() == 200) {
resultString = EntityUtils.toString(entity, "UTF-8");
return resultString;
}
} catch (Exception e) {
throw e;
} finally {
EntityUtils.consume(entity);
entity = null;
}
return resultString;
}
});
ThreadPool.execute(fu);
String content = fu.get(connectTimeout, TimeUnit.MILLISECONDS);
return content;
}
private static DefaultHttpClient getClient(int connectTimeout, int socketTimeout, boolean isSSL) throws Exception {
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectTimeout);
client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout);
if (isSSL) {
client.getConnectionManager().getSchemeRegistry().register(getHttpsSupportScheme());
}
return client;
}
private static Scheme getHttpsSupportScheme() {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
return new Scheme("https", 443, ssf);
} catch (NoSuchAlgorithmException e) {
return null;
} catch (KeyManagementException e) {
return null;
}
}
}