package com.xxxx.util;
import org.apache.http.*;
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.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author weichangzhong
*/
public class HttpClientUtil {
private static final int DEFAULT_MAX_CONN_PER_ROUTE = 200;
private static final int DEFAULT_MAX_CONN_TOTAL = 400;
/**
* 设置超时时间
*/
private static final int DEFAULT_CONNECTION_TIMEOUT = 200;
private static final int DEFAULT_SO_TIMEOUT = 150;
private static final String PARAMETER_ENCODING = "UTF-8";
private static CloseableHttpClient client = null;
private static PoolingHttpClientConnectionManager ccm;
/**
* 创建HttpClientBuilder
*/
private static HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
static {
// TODO 根据不同的请求路线设置不同的线程池大小,因为每个路线的耗时情况不同
ccm = new PoolingHttpClientConnectionManager();
ccm.setMaxTotal(DEFAULT_MAX_CONN_TOTAL);
ccm.setDefaultMaxPerRoute(DEFAULT_MAX_CONN_PER_ROUTE);
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setSocketTimeout(DEFAULT_SO_TIMEOUT)
.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT)
.setConnectionRequestTimeout(DEFAULT_CONNECTION_TIMEOUT)
.build();
client = httpClientBuilder
.setConnectionManager(ccm)
.setDefaultRequestConfig(defaultRequestConfig)
.build();
}
/**
* 发送Get请求
*
* @param url 请求地址
* @param paramMap 请求参数
* @param headerMap Header参数
* @param encoding 响应的编码
* @return
*/
public static String get(String url, Map paramMap, Map headerMap, String encoding) {
if (paramMap != null && !paramMap.isEmpty()) {
List params = new ArrayList();
for (String key : paramMap.keySet()) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
String queryString = URLEncodedUtils.format(params, PARAMETER_ENCODING);
if (url.indexOf("?") > -1) {
url += "&" + queryString;
} else {
url += "?" + queryString;
}
}
// 创建Get实例
HttpGet httpGet = new HttpGet(url);
// 是否需要设置Header
if (headerMap != null && !headerMap.isEmpty()) {
Set keySet = headerMap.keySet();
for (String key : keySet) {
httpGet.addHeader(key, headerMap.get(key));
}
}
String result = null;
try {
HttpResponse response = client.execute(httpGet);
StatusLine status = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (status.getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, encoding);
} else {
httpGet.abort();
logger.error("Unable to fetch page {}, status code: {}, error", httpGet.getURI(), status.getStatusCode());
}
} catch (Exception e) {
logger.error("url: {}, error: {}", url, e.getMessage());
logger.debug("{}", e);
if (httpGet != null) {
httpGet.abort();
}
} finally {
if (httpGet != null) {
httpGet.releaseConnection();
}
}
return result;
}
/**
* 发送Post请求
*
* @param url Post请求URL
* @param paramMap 参数
* @param headerMap Header参数
* @param encoding 响应的编码
* @return
*/
private static String post(HttpClient client, String url, Map paramMap, Map headerMap, String encoding) {
// 创建Post实例
HttpPost httpPost = new HttpPost(url);
List params = new ArrayList();
if (paramMap != null && !paramMap.isEmpty()) {
Set keySet = paramMap.keySet();
for (String key : keySet) {
params.add(new BasicNameValuePair(key, paramMap.get(key)));
}
}
// 是否需要设置Header
if (headerMap != null && !headerMap.isEmpty()) {
Set keySet = headerMap.keySet();
for (String key : keySet) {
httpPost.addHeader(key, headerMap.get(key));
}
}
String result = null;
try {
httpPost.setEntity(new UrlEncodedFormEntity(params, encoding));
HttpResponse response = client.execute(httpPost);
StatusLine status = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (status.getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(entity, encoding);
} else {
httpPost.abort();
result = EntityUtils.toString(entity, encoding);
logger.error("Unable to fetch page {}, status code: {}", httpPost.getURI(), status.getStatusCode());
}
} catch (Exception e) {
logger.error("url: {}, error: {}", url, e.getMessage());
logger.debug("", e);
if (httpPost != null) {
httpPost.abort();
}
} finally {
if (httpPost != null) {
httpPost.releaseConnection();
}
}
return result;
}
/**
* 二进制流数据进行POST通信
* @param url
* @param bytes
* @param headerMap
* @return
*/
public static byte[] post(String url, byte[] bytes, Map headerMap) {
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new ByteArrayEntity(bytes));
HttpResponse httpResponse = null;
byte[] resBytes = null;
// 是否需要设置Header
if (headerMap != null && !headerMap.isEmpty()) {
Set keySet = headerMap.keySet();
for (String key : keySet) {
httpPost.addHeader(key, headerMap.get(key));
}
}
try {
httpResponse = client.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
int contentLength = (int)httpEntity.getContentLength();
resBytes = new byte[contentLength];
// 由于返回的结果可能一次性读不完,所以用buff保存每次读取的数据,而当某次读取到的长度返回值为-1时表示读取结束
byte[] buff = new byte[contentLength];
int total = 0;
int len;
while ((len = httpEntity.getContent().read(buff)) != -1) {
for(int i = 0; i < len; i++) {
resBytes[total+i] = buff[i];
}
total = total + len;
}
if(total != contentLength) {
logger.error("Read http post response buffer error, [{}]", url);
}
} catch (Exception e) {
logger.error("Something went wrong when call http post url: [{}]", url, e);
}finally {
if(httpPost != null) {
httpPost.releaseConnection();
}
}
return resBytes;
}
}