com.rt.core.util.HttpUtil Maven / Gradle / Ivy
The newest version!
package com.rt.core.util;
import com.json.JSONArray;
import com.json.JSONObject;
import com.rt.core.beans.IOCallback;
import com.rt.core.beans.UrlFile;
import com.rt.core.util.RTUtil;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.client.entity.UrlEncodedFormEntity;
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.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
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.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class HttpUtil {
/**
* 连接池最大线程数
*/
private static final int MAX_THREAD = 300;
/**
* 每Route最大线程数
*/
private static final int MAX_THREAD_PER_ROUTE = 150;
/**
* 默认统一超时时间
*/
private static final int MAX_TIMEOUT = 10000;
/**
* 闲置时间
*/
public static final int MAX_IDLE_TIMEOUT = 3000;
/**
* User-Agents
*/
// private static final String UA_ORIGIN = "Apache-HttpClient/4.5.2";
private static final String UA_FIREFOX = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:53.0) Gecko/20100101 Firefox/53.0";
private static final String UA = UA_FIREFOX;
/**
* 默认编码
*/
public static final String DEFAULT_CHARSET = "UTF-8";
/**
* 连接池
*/
private static PoolingHttpClientConnectionManager connectionManager;
/** 空闲链接监控线程 */
// private static IdleConnectionMonitorThread idleConnectionMonitorThread;
static {
connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(MAX_THREAD);
connectionManager.setDefaultMaxPerRoute(MAX_THREAD_PER_ROUTE);
// idleConnectionMonitorThread = new IdleConnectionMonitorThread(
// connectionManager);
// idleConnectionMonitorThread.start();
// try {
// idleConnectionMonitorThread.join(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}
/**
* 关闭空闲链接监控线程
*/
// public static void shutdownIdleConnectionMonitorThread() {
// idleConnectionMonitorThread.shutdown();
// }
/**
* GET请求,返回字符串 HTTPS请求通过url以https开头来激活
*
* @param url url
* @param params 参数
* @param charset 编码
* @return 响应字符串
* @throws Exception Exception
*/
public static String doGet4String(String url, Map headers,
Map params, String charset, int timeout, boolean checkSsl)
throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
byte[] resultBytes = doGet4ByteArray(url, headers, params, charset, timeout, checkSsl);
return new String(resultBytes, Charset.forName(charset));
}
/**
* GET请求,返回byte数组 HTTPS请求通过url以https开头来激活
*
* @param url url
* @param params 参数
* @param charset 编码
* @return 响应byte数组
* @throws Exception Exception
*/
public static byte[] doGet4ByteArray(String url,
Map headers, Map params,
String charset, int timeout, boolean checkSsl) throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
byte[] result = null;
List pairList = param2PairList(params);
CloseableHttpClient httpclient = buildHTTPClient(url, checkSsl);
URIBuilder URIBuilder = new URIBuilder(url);
URIBuilder.setCharset(Charset.forName(charset));
if (pairList.size() > 0) {
URIBuilder.addParameters(pairList);
}
URI uri = URIBuilder.build();
HttpGet httpGet = new HttpGet(uri);
httpGet.setConfig(buildRequestConfig(timeout));
for (String hkey : headers.keySet()) {
httpGet.setHeader(hkey, headers.get(hkey));
}
CloseableHttpResponse response = httpclient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toByteArray(entity);
}
EntityUtils.consume(entity);
return result;
}
/**
* POST请求,返回字符串
*
* @param url
* @param headers
* @param params
* @param charset
* @param timeout
* @return String
* @throws Exception
*/
public static String doPost4String(String url, Map headers,
Map params, String charset, int timeout, boolean checkSsl)
throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
List pairList = param2PairList(params);
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset
.forName(charset)));
return sendPost4String(url, httpPost, headers, charset, timeout, checkSsl);
}
/**
* POST请求,返回byte数组
*
* @param url
* @param headers
* @param params
* @param charset
* @param timeout
* @return byte[]
* @throws Exception
*/
public static byte[] doPost4ByteArray(String url,
Map headers, Map params,
String charset, int timeout, boolean checkSsl) throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
List pairList = param2PairList(params);
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(pairList, Charset
.forName(charset)));
return doPost(url, httpPost, headers, timeout, checkSsl);
}
/**
* 文件上传POST请求
*
* @param url url
* @param params 参数
* @param charset 编码
* @return 响应字符串
* @throws Exception Exception
*/
public static String doMultipartPost(String url,
Map headers, Map params,
String charset, int timeout, boolean checkSsl) throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
HttpEntity entity = buildMultipartEntity(params, charset);
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(entity);
return sendPost4String(url, httpPost, headers, charset, timeout, checkSsl);
}
/**
* POST请求,发送字符串,返回字符串
*
* @param url
* @param headers
* @param str
* @param charset
* @param timeout
* @param contentType
* @return String
* @throws Exception
*/
public static String doPostString4String(String url,
Map headers, String str, String charset,
int timeout, boolean checkSsl, String contentType) throws Exception {
if (RTUtil.isEmpty(url)) {
return null;
}
if (headers == null) {
headers = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
HttpPost httpPost = new HttpPost(url);
StringEntity stringEntity = new StringEntity(str, charset);
if (RTUtil.isNotEmpty(contentType)) {
stringEntity.setContentType(contentType);
}
httpPost.setEntity(stringEntity);
return sendPost4String(url, httpPost, headers, charset, timeout, checkSsl);
}
/**
* POST请求,返回字符串(XML版)
*
* @param url url
* @param xml xml参数
* @return 响应字符串
* @throws Exception
*/
public static String doPostXML4String(String url,
Map headers, String xml, int timeout, boolean checkSsl)
throws Exception {
return doPostString4String(url, headers, xml, DEFAULT_CHARSET, timeout, checkSsl,
"application/xml");
}
/**
* POST请求,返回字符串(JSON版)
*
* @param url
* @param headers
* @param json
* @param timeout
* @return String
* @throws Exception
*/
public static String doPostJSON4String(String url, Map headers, String json,
int timeout, boolean checkSsl)
throws Exception {
return doPostString4String(url, headers, json, DEFAULT_CHARSET,
timeout, checkSsl, "application/json");
}
/**
* 内部方法 POST 请求,返回字符串
*
* @param url
* @param httpPost
* @param headers
* @param charset
* @param timeout
* @return String
* @throws ClientProtocolException
* @throws IOException
* @throws KeyManagementException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
*/
private static String sendPost4String(String url, HttpPost httpPost,
Map headers, String charset, int timeout, boolean checkSsl)
throws ClientProtocolException, IOException,
KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
byte[] resultBytes = doPost(url, httpPost, headers, timeout, checkSsl);
return new String(resultBytes, Charset.forName(charset));
}
/**
* 内部方法 POST 请求,返回byte数组
*
* @param url
* @param httpPost
* @param headers
* @param timeout
* @return byte[]
* @throws ClientProtocolException
* @throws IOException
* @throws KeyManagementException
* @throws NoSuchAlgorithmException
* @throws KeyStoreException
*/
private static byte[] doPost(String url, HttpPost httpPost,
Map headers, int timeout, boolean checkSsl)
throws ClientProtocolException, IOException,
KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
CloseableHttpClient httpClient = buildHTTPClient(url, checkSsl);
byte[] result = null;
httpPost.setConfig(buildRequestConfig(timeout));
for (String hkey : headers.keySet()) {
httpPost.setHeader(hkey, headers.get(hkey));
}
CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (entity != null) {
result = EntityUtils.toByteArray(entity);
}
EntityUtils.consume(entity);
return result;
}
public static void doPostProcess(String url, Map headers, Map params,
String charset, int timeout, boolean checkSsl,
IOCallback outputCallback) throws Exception {
if (RTUtil.isEmpty(url)) {
return;
}
if (params == null) {
params = new HashMap<>();
}
if (RTUtil.isEmpty(charset)) {
charset = DEFAULT_CHARSET;
}
CloseableHttpClient httpClient = buildHTTPClient(url, checkSsl);
HttpPost httpPost = new HttpPost(url);
HttpEntity reqEntity = buildMultipartEntity(params, charset);
httpPost.setEntity(reqEntity);
httpPost.setConfig(buildRequestConfig(timeout));
for (String hkey : headers.keySet()) {
httpPost.setHeader(hkey, headers.get(hkey));
}
CloseableHttpResponse response = httpClient.execute(httpPost);
JSONObject info = new JSONObject();
Header[] responseHeaders = response.getHeaders("Set-Cookie");
for (Header responseHeader : responseHeaders) {
HeaderElement[] headerElements = responseHeader.getElements();
for (HeaderElement headerElement : headerElements) {
info.put(headerElement.getName(), headerElement.getValue());
}
}
outputCallback.headerInfo(info);
HttpEntity entity = response.getEntity();
int state = response.getStatusLine().getStatusCode();
if (HttpStatus.SC_OK != state) {
outputCallback.responseNot200(httpClient, response);
EntityUtils.consume(entity);
return;
}
// 获取文件长度
final long fileLength = entity.getContentLength();
OutputStream outputStream = outputCallback.getOutputStream();
if (outputStream == null) {
return;
}
InputStream inputStream = entity.getContent();
int read;
long readCount = 0;
int index = 0;
int buffer = outputCallback.getBufferSize();
// 使用指定缓存
if (buffer > 0) {
byte[] bufferByte = new byte[buffer];
while ((read = inputStream.read(bufferByte)) != -1) {
outputStream.write(bufferByte, 0, read);
readCount += read;
outputCallback
.outputProcess(fileLength, read, index, readCount);
index++;
}
} else {
// 使用默认缓存
while ((read = inputStream.read()) != -1) {
outputStream.write(read);
readCount += read;
outputCallback
.outputProcess(fileLength, read, index, readCount);
index++;
}
}
EntityUtils.consume(entity);
}
/**
* 构建HttpClient实例
*
* @param url
* @return CloseableHttpClient
* @throws KeyManagementException KeyManagementException
* @throws NoSuchAlgorithmException NoSuchAlgorithmException
* @throws KeyStoreException KeyStoreException
*/
private static CloseableHttpClient buildHTTPClient(String url, boolean checkSsl)
throws KeyManagementException, NoSuchAlgorithmException,
KeyStoreException {
boolean isSsl = url.toLowerCase().startsWith("https:");
if (isSsl) {
if (checkSsl) {
SSLContext sslContext = SSLContexts
.custom()
.loadTrustMaterial((KeyStore) null,
TrustSelfSignedStrategy.INSTANCE).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
HttpClientBuilder clientBuilder = HttpClients.custom().setUserAgent(UA)
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(buildRequestConfig(MAX_TIMEOUT));
clientBuilder.setSSLSocketFactory(sslsf);
return clientBuilder.build();
} else {
SSLContext sslContext = SSLContext.getInstance("SSLv3");
// X509TrustManager 用于绕过验证,不用修改里面的方法
X509TrustManager x509TrustManager = 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.init(null, new TrustManager[]{x509TrustManager}, null);
Registry registry = RegistryBuilder.create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslContext))
.build();
connectionManager = new PoolingHttpClientConnectionManager(registry);
}
}
HttpClientBuilder clientBuilder = HttpClients.custom().setUserAgent(UA)
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(buildRequestConfig(MAX_TIMEOUT));
return clientBuilder.build();
}
/**
* Map 转 NameValuePair
*
* @param params 请求参数
* @return NameValuePair列表
*/
private static List param2PairList(Map params) {
if (params == null) {
params = new HashMap();
}
List pairList = new ArrayList(
params.size());
for (String key : params.keySet()) {
Object value = params.get(key);
if (value == null) {
continue;
}
pairList.add(new BasicNameValuePair(key, value.toString()));
}
return pairList;
}
/**
* Map 转 HttpEntity
*
* @param params 请求参数
* @return HttpEntity
* @throws Exception Exception
*/
private static HttpEntity buildMultipartEntity(Map params,
String charset) throws Exception {
if (params == null || params.isEmpty()) {
return null;
}
Charset charsetValue = Charset.forName(charset);
MultipartEntityBuilder builder = MultipartEntityBuilder
.create()
.setMode(HttpMultipartMode.RFC6532)
.setCharset(Charset.forName(charset))
.setContentType(
ContentType.MULTIPART_FORM_DATA
.withCharset(charsetValue));
for (String key : params.keySet()) {
Object value = params.get(key);
if (value == null) {
continue;
}
if (value instanceof UrlFile) {
UrlFile urlFile = (UrlFile) value;
String fileName = urlFile.getFilename();
if (RTUtil.isEmpty(fileName)) {
fileName = String.valueOf(RTUtil.getUUID());
}
ByteArrayBody contentBody = new ByteArrayBody(
urlFile.getByteFile(), fileName);
builder.addPart(key, contentBody);
} else if (value instanceof JSONArray) {
JSONArray array = (JSONArray) value;
for (int i = 0; i < array.length(); i++) {
Object innerValue = array.get(i);
if (innerValue instanceof UrlFile) {
UrlFile urlFile = (UrlFile) innerValue;
String fileName = urlFile.getFilename();
if (RTUtil.isEmpty(fileName)) {
fileName = String.valueOf(i);
}
ByteArrayBody contentBody = new ByteArrayBody(urlFile.getByteFile(), fileName);
builder.addPart(key, contentBody);
} else {
builder.addTextBody(key, value.toString(),
ContentType.TEXT_PLAIN
.withCharset(charsetValue));
}
}
} else {
builder.addTextBody(key, value.toString(),
ContentType.TEXT_PLAIN.withCharset(charsetValue));
}
}
return builder.build();
}
/**
* 创建请求参数
*
* @param timeout 超时时间
* @return 请求参数
*/
private static RequestConfig buildRequestConfig(int timeout) {
Builder configBuilder = RequestConfig.custom();
configBuilder.setConnectTimeout(timeout);
configBuilder.setSocketTimeout(timeout);
configBuilder.setConnectionRequestTimeout(timeout);
return configBuilder.build();
}
}