|
|
@@ -0,0 +1,458 @@ |
|
|
|
package cc.smtweb.framework.core.util; |
|
|
|
|
|
|
|
import cc.smtweb.framework.core.common.SwMap; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.apache.commons.codec.binary.Base64; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.apache.http.*; |
|
|
|
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.config.Registry; |
|
|
|
import org.apache.http.config.RegistryBuilder; |
|
|
|
import org.apache.http.conn.HttpClientConnectionManager; |
|
|
|
import org.apache.http.conn.socket.ConnectionSocketFactory; |
|
|
|
import org.apache.http.conn.socket.PlainConnectionSocketFactory; |
|
|
|
import org.apache.http.conn.ssl.NoopHostnameVerifier; |
|
|
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
|
|
|
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.client.LaxRedirectStrategy; |
|
|
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
|
|
|
import org.apache.http.message.BasicNameValuePair; |
|
|
|
import org.apache.http.ssl.SSLContextBuilder; |
|
|
|
import org.apache.http.ssl.TrustStrategy; |
|
|
|
import org.apache.http.util.EntityUtils; |
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.security.cert.CertificateException; |
|
|
|
import java.security.cert.X509Certificate; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.function.Consumer; |
|
|
|
|
|
|
|
/** |
|
|
|
* Created by Akmm at 2017/7/4 16:58 |
|
|
|
* http辅助类,支持http/https |
|
|
|
*/ |
|
|
|
@Slf4j |
|
|
|
public class HttpUtil { |
|
|
|
private static final String HTTP = "http"; |
|
|
|
private static final String HTTPS = "https"; |
|
|
|
private static SSLConnectionSocketFactory sslsf = null; |
|
|
|
private static PoolingHttpClientConnectionManager cm = null; |
|
|
|
private static SSLContextBuilder builder = null; |
|
|
|
private static RequestConfig requestConfig = null; |
|
|
|
|
|
|
|
private static final Integer MAX_TOTAL = 200; //连接池最大连接数 |
|
|
|
private static final Integer MAX_PER_ROUTE = 100; //单个路由默认最大连接数 |
|
|
|
private static final Integer REQ_TIMEOUT = 10 * 1000; //请求超时时间ms |
|
|
|
private static final Integer CONN_TIMEOUT = 10 * 1000; //连接超时时间ms |
|
|
|
private static final Integer SOCK_TIMEOUT = 5 * 60 * 1000; //读取超时时间ms |
|
|
|
private static HttpClientConnectionMonitorThread thread; //HTTP链接管理器线程 |
|
|
|
|
|
|
|
|
|
|
|
static { |
|
|
|
try { |
|
|
|
builder = new SSLContextBuilder(); |
|
|
|
// 全部信任 不做身份鉴定 |
|
|
|
builder.loadTrustMaterial(null, new TrustStrategy() { |
|
|
|
@Override |
|
|
|
public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { |
|
|
|
return true; |
|
|
|
} |
|
|
|
}); |
|
|
|
sslsf = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE); |
|
|
|
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() |
|
|
|
.register(HTTP, new PlainConnectionSocketFactory()) |
|
|
|
.register(HTTPS, sslsf) |
|
|
|
.build(); |
|
|
|
cm = new PoolingHttpClientConnectionManager(registry); |
|
|
|
cm.setMaxTotal(MAX_TOTAL);//max connection |
|
|
|
cm.setDefaultMaxPerRoute(MAX_PER_ROUTE); |
|
|
|
thread = new HttpClientConnectionMonitorThread(cm); |
|
|
|
|
|
|
|
requestConfig = RequestConfig.custom() |
|
|
|
.setConnectionRequestTimeout(REQ_TIMEOUT) //从连接池中获取连接的超时时间 |
|
|
|
//与服务器连接超时时间:httpclient会创建一个异步线程用以创建socket连接,此处设置该socket的连接超时时间 |
|
|
|
.setConnectTimeout(CONN_TIMEOUT) |
|
|
|
.setSocketTimeout(SOCK_TIMEOUT) //socket读数据超时时间:从服务器获取响应数据的超时时间 |
|
|
|
.build(); |
|
|
|
} catch (Exception e) { |
|
|
|
e.printStackTrace(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* http调用 |
|
|
|
* |
|
|
|
* @param url 请求地址 |
|
|
|
* @param paras 参数,name,value形式 |
|
|
|
* @return |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static SwMap post(String url, String... paras) throws Exception { |
|
|
|
SwMap map = new SwMap(); |
|
|
|
int n = 0; |
|
|
|
while (n < paras.length) { |
|
|
|
map.put(paras[n++], paras[n++]); |
|
|
|
} |
|
|
|
return post(url, map); |
|
|
|
} |
|
|
|
|
|
|
|
public static SwMap post(String url, Map<String, String> paras) throws Exception { |
|
|
|
String json_resp = post(url, null, paras, null); |
|
|
|
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null; |
|
|
|
return (SwMap) JsonUtil.parseMap(json_resp); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Post 请求 |
|
|
|
* |
|
|
|
* @param url 请求url |
|
|
|
* @param paras json 格式参数 |
|
|
|
* @return |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static SwMap post(String url, SwMap paras) throws Exception { |
|
|
|
return post(url, paras, false); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Post 请求 |
|
|
|
* |
|
|
|
* @param url 请求url |
|
|
|
* @param paras json 参数 |
|
|
|
* @param encode json 是否加密传输 |
|
|
|
* @return |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static SwMap post(String url, SwMap paras, boolean encode) throws Exception { |
|
|
|
return post(url, paras, encode, null); |
|
|
|
} |
|
|
|
|
|
|
|
public static SwMap post(String url, SwMap paras, boolean encode, String charset) throws Exception { |
|
|
|
if (StringUtils.isEmpty(charset)) charset = "UTF-8"; |
|
|
|
String param = JsonUtil.encodeString(paras); |
|
|
|
if (encode) param = Base64.encodeBase64String(param.getBytes(charset)); |
|
|
|
StringEntity entity = new StringEntity(param, charset);//解决中文乱码问题 |
|
|
|
entity.setContentEncoding(charset); |
|
|
|
entity.setContentType("application/json"); |
|
|
|
String json_resp = post(url, null, null, entity, charset); |
|
|
|
if (encode && !json_resp.startsWith("{")) {//加密传输时,解密 |
|
|
|
json_resp = new String(Base64.decodeBase64(json_resp),charset); |
|
|
|
} |
|
|
|
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null; |
|
|
|
return (SwMap)JsonUtil.parseMap(json_resp); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 加密请求 |
|
|
|
* |
|
|
|
* @param url |
|
|
|
* @param paras |
|
|
|
* @param encode |
|
|
|
* @return |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static SwMap post(String url, Map<String, String> paras, boolean encode) throws Exception { |
|
|
|
return post(url, paras, encode, null); |
|
|
|
} |
|
|
|
|
|
|
|
public static SwMap post(String url, Map<String, String> paras, boolean encode, String charset) throws Exception { |
|
|
|
String json_resp = post(url, null, paras, null, charset); |
|
|
|
if (encode) { |
|
|
|
json_resp = new String(Base64.decodeBase64(json_resp),charset); |
|
|
|
} |
|
|
|
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null; |
|
|
|
return (SwMap)JsonUtil.parseMap(json_resp); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static SwMap post(String url,Map<String, String> header, Map<String, String> paras) throws Exception { |
|
|
|
String json_resp = post(url, header, paras, null); |
|
|
|
if (StringUtils.isEmpty(json_resp) || !json_resp.startsWith("{")) return null; |
|
|
|
return (SwMap) JsonUtil.parseMap(json_resp); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* httpClient post请求 |
|
|
|
* |
|
|
|
* @param url 请求url |
|
|
|
* @param header 头部信息 |
|
|
|
* @param param 请求参数 form提交适用 |
|
|
|
* @param entity 请求实体 json/xml提交适用 |
|
|
|
* @return 可能为空 需要处理 |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static String post(String url, Map<String, String> header, Map<String, String> param, HttpEntity entity) throws Exception { |
|
|
|
return post(url, header, param, entity, null); |
|
|
|
} |
|
|
|
public static String post(String url, Map<String, String> header, Map<String, String> param, HttpEntity entity, String charset) throws Exception { |
|
|
|
return postEx(url,header,param,entity,charset,null); |
|
|
|
} |
|
|
|
public static String postEx(String url, Map<String, String> header, Map<String, String> param, HttpEntity entity, String charset, Consumer<Header[]> headerWorker) throws Exception { |
|
|
|
if (StringUtils.isEmpty(charset)) charset = "UTF-8"; |
|
|
|
String result = ""; |
|
|
|
CloseableHttpClient httpClient = null; |
|
|
|
HttpResponse httpResponse = null; |
|
|
|
try { |
|
|
|
httpClient = getHttpClient(); |
|
|
|
HttpPost httpPost = getHttpPost(url); |
|
|
|
// 设置头信息 |
|
|
|
if (header!=null && header.size()>0) { |
|
|
|
for (Map.Entry<String, String> entry : header.entrySet()) { |
|
|
|
httpPost.addHeader(entry.getKey(), entry.getValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
// 设置请求参数 |
|
|
|
if (param!=null && param.size()>0) { |
|
|
|
List<NameValuePair> formparams = new ArrayList<>(); |
|
|
|
for (Map.Entry<String, String> entry : param.entrySet()) { |
|
|
|
//给参数赋值 |
|
|
|
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); |
|
|
|
} |
|
|
|
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(formparams, charset); |
|
|
|
httpPost.setEntity(urlEncodedFormEntity); |
|
|
|
} |
|
|
|
// 设置实体 优先级高 |
|
|
|
if (entity != null) { |
|
|
|
httpPost.setEntity(entity); |
|
|
|
} |
|
|
|
httpResponse = httpClient.execute(httpPost); |
|
|
|
int statusCode = httpResponse.getStatusLine().getStatusCode(); |
|
|
|
if (statusCode == HttpStatus.SC_OK) { |
|
|
|
if(headerWorker!=null){ |
|
|
|
headerWorker.accept(httpResponse.getAllHeaders()); |
|
|
|
} |
|
|
|
HttpEntity resEntity = httpResponse.getEntity(); |
|
|
|
result = EntityUtils.toString(resEntity, charset); |
|
|
|
EntityUtils.consume(resEntity); |
|
|
|
} else { |
|
|
|
result = readHttpResponse(httpResponse); |
|
|
|
} |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("POST_ERROR:",e); |
|
|
|
} finally { |
|
|
|
if (httpClient != null) { |
|
|
|
httpClient.close(); |
|
|
|
} |
|
|
|
if (httpResponse != null) { |
|
|
|
HttpEntity httpEntity = httpResponse.getEntity(); |
|
|
|
if (httpEntity != null) { |
|
|
|
EntityUtils.consume(httpEntity); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* httpClient post请求 |
|
|
|
* |
|
|
|
* @param url 请求url |
|
|
|
* @param header 头部信息 |
|
|
|
* @return 可能为空 需要处理 |
|
|
|
* @throws Exception |
|
|
|
*/ |
|
|
|
public static String get(String url, Map<String, String> header) throws Exception { |
|
|
|
String result = ""; |
|
|
|
CloseableHttpClient httpClient = null; |
|
|
|
HttpResponse httpResponse = null; |
|
|
|
try { |
|
|
|
httpClient = HttpUtil.getHttpClient(); |
|
|
|
HttpGet httpGet = new HttpGet(url); |
|
|
|
httpGet.setConfig(requestConfig); |
|
|
|
// 设置头信息 |
|
|
|
if (header!=null && header.size()>0) { |
|
|
|
for (Map.Entry<String, String> entry : header.entrySet()) { |
|
|
|
httpGet.addHeader(entry.getKey(), entry.getValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
httpResponse = httpClient.execute(httpGet); |
|
|
|
int statusCode = httpResponse.getStatusLine().getStatusCode(); |
|
|
|
if (statusCode == HttpStatus.SC_OK) { |
|
|
|
HttpEntity resEntity = httpResponse.getEntity(); |
|
|
|
result = EntityUtils.toString(resEntity); |
|
|
|
EntityUtils.consume(resEntity); |
|
|
|
} else { |
|
|
|
result = readHttpResponse(httpResponse); |
|
|
|
} |
|
|
|
} finally { |
|
|
|
if (httpClient != null) { |
|
|
|
httpClient.close(); |
|
|
|
} |
|
|
|
if (httpResponse != null) { |
|
|
|
HttpEntity httpEntity = httpResponse.getEntity(); |
|
|
|
if (httpEntity != null) { |
|
|
|
EntityUtils.consume(httpEntity); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
public static CloseableHttpClient getHttpClient() throws Exception { |
|
|
|
// thread = new HttpClientConnectionMonitorThread(cm); |
|
|
|
CloseableHttpClient httpClient = HttpClients.custom() |
|
|
|
.setSSLSocketFactory(sslsf) |
|
|
|
.setConnectionManager(cm) |
|
|
|
.setConnectionManagerShared(true) |
|
|
|
.disableAutomaticRetries() //关闭自动处理重定向 |
|
|
|
.setRedirectStrategy(new LaxRedirectStrategy())//利用LaxRedirectStrategy处理POST重定向问题 |
|
|
|
.setDefaultRequestConfig(requestConfig) |
|
|
|
.build(); |
|
|
|
|
|
|
|
return httpClient; |
|
|
|
} |
|
|
|
|
|
|
|
public static HttpPost getHttpPost(String url) { |
|
|
|
HttpPost httpPost = new HttpPost(url); |
|
|
|
httpPost.setConfig(requestConfig); |
|
|
|
return httpPost; |
|
|
|
} |
|
|
|
|
|
|
|
private static String readHttpResponse(HttpResponse httpResponse) |
|
|
|
throws ParseException, IOException { |
|
|
|
StringBuilder builder = new StringBuilder(); |
|
|
|
// 获取响应消息实体 |
|
|
|
HttpEntity entity = httpResponse.getEntity(); |
|
|
|
// 响应状态 |
|
|
|
builder.append("status:" + httpResponse.getStatusLine()); |
|
|
|
builder.append("headers:"); |
|
|
|
HeaderIterator iterator = httpResponse.headerIterator(); |
|
|
|
while (iterator.hasNext()) { |
|
|
|
builder.append("\t" + iterator.next()); |
|
|
|
} |
|
|
|
// 判断响应实体是否为空 |
|
|
|
if (entity != null) { |
|
|
|
String responseString = EntityUtils.toString(entity); |
|
|
|
builder.append("response length:" + responseString.length()); |
|
|
|
builder.append("response content:" + responseString.replace("\r\n", "")); |
|
|
|
} |
|
|
|
return builder.toString(); |
|
|
|
} |
|
|
|
|
|
|
|
public static void main(String[] args) throws Exception { |
|
|
|
|
|
|
|
|
|
|
|
// //用线程池发送请求 |
|
|
|
// ExecutorService executor = Executors.newFixedThreadPool(3); |
|
|
|
// |
|
|
|
// Thread t1 = new Thread(new Runnable() { |
|
|
|
// @Override |
|
|
|
// public void run() { |
|
|
|
// for (int i = 0; i < 100; i++) { |
|
|
|
// HttpPost post = getHttpPost("http://127.0.0.1:8080/qhmz/receiveBankData.do"); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【receiveBankData】"); |
|
|
|
// try { |
|
|
|
// CloseableHttpClient httpclient = UtilHttp.getHttpClient(); |
|
|
|
// CloseableHttpResponse response2 = httpclient.execute(post); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】,结果" + response2.getStatusLine()); |
|
|
|
// httpclient.close(); |
|
|
|
// EntityUtils.consume(response2.getEntity()); |
|
|
|
// } catch (Exception e) { |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】" + UtilPub.getOrigMsg(e)); |
|
|
|
// } |
|
|
|
// |
|
|
|
// } |
|
|
|
// } |
|
|
|
// }); |
|
|
|
// Thread t2 = new Thread(new Runnable() { |
|
|
|
// @Override |
|
|
|
// public void run() { |
|
|
|
// for (int i = 0; i < 100; i++) { |
|
|
|
// HttpPost post = getHttpPost("http://127.0.0.1:8080/qhmz/cust/ebank/biz/service.do"); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【service】"); |
|
|
|
// try { |
|
|
|
// CloseableHttpClient httpclient = UtilHttp.getHttpClient(); |
|
|
|
// CloseableHttpResponse response2 = httpclient.execute(post); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】,结果" + response2.getStatusLine()); |
|
|
|
// httpclient.close(); |
|
|
|
// EntityUtils.consume(response2.getEntity()); |
|
|
|
// } catch (Exception e) { |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】" + UtilPub.getOrigMsg(e)); |
|
|
|
// } |
|
|
|
// |
|
|
|
// } |
|
|
|
// } |
|
|
|
// }); |
|
|
|
// Thread t3 = new Thread(new Runnable() { |
|
|
|
// @Override |
|
|
|
// public void run() { |
|
|
|
// for (int i = 0; i < 100; i++) { |
|
|
|
// HttpPost post = getHttpPost("http://127.0.0.1:8080/qhmz/cust/ebank/biz/isSupBank.do"); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【isSupBank】"); |
|
|
|
// try { |
|
|
|
// CloseableHttpClient httpclient = UtilHttp.getHttpClient(); |
|
|
|
// CloseableHttpResponse response2 = httpclient.execute(post); |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】,结果" + response2.getStatusLine()); |
|
|
|
// httpclient.close(); |
|
|
|
// EntityUtils.consume(response2.getEntity()); |
|
|
|
// } catch (Exception e) { |
|
|
|
// System.out.println("请求第【" + (i + 1) + "】次:【" + post.getURI() + "】" + UtilPub.getOrigMsg(e)); |
|
|
|
// } |
|
|
|
// |
|
|
|
// } |
|
|
|
// } |
|
|
|
// }); |
|
|
|
// executor.execute(t1); |
|
|
|
// executor.execute(t2); |
|
|
|
// executor.execute(t3); |
|
|
|
// executor.shutdown(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* <p>Description: 使用管理器,管理HTTP连接池 无效链接定期清理功能</p> |
|
|
|
* |
|
|
|
* @author andy 2017年8月28日 |
|
|
|
*/ |
|
|
|
public static class HttpClientConnectionMonitorThread extends Thread { |
|
|
|
|
|
|
|
private final HttpClientConnectionManager connManager; |
|
|
|
private volatile boolean shutdown; |
|
|
|
|
|
|
|
public HttpClientConnectionMonitorThread(HttpClientConnectionManager connManager) { |
|
|
|
super(); |
|
|
|
this.setName("http-connection-monitor"); |
|
|
|
this.setDaemon(true); |
|
|
|
this.connManager = connManager; |
|
|
|
this.start(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
try { |
|
|
|
while (!shutdown) { |
|
|
|
synchronized (this) { |
|
|
|
wait(5000); // 等待5秒 |
|
|
|
// 关闭过期的链接 |
|
|
|
connManager.closeExpiredConnections(); |
|
|
|
// 选择关闭 空闲30秒的链接 |
|
|
|
connManager.closeIdleConnections(30, TimeUnit.SECONDS); |
|
|
|
} |
|
|
|
} |
|
|
|
} catch (InterruptedException ex) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 方法描述: 停止 管理器 清理无效链接 (该方法当前暂时关闭) |
|
|
|
* |
|
|
|
* @author andy 2017年8月28日 下午1:45:18 |
|
|
|
*/ |
|
|
|
@Deprecated |
|
|
|
public void shutDownMonitor() { |
|
|
|
synchronized (this) { |
|
|
|
shutdown = true; |
|
|
|
notifyAll(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |