接著上一篇,總結(jié)一下HttpClient發(fā)送https請求相關(guān)的內(nèi)容霸奕。
先簡單介紹連接工廠(interface org.apache.http.conn.socket.ConnectionSocketFactory
)炕横,連接工廠主要用于創(chuàng)建蘑斧、初始化油够、連接socket菌瘪。org.apache.http.conn.socket.PlainConnectionSocketFactory
是默認(rèn)的socket工廠腮敌,用于創(chuàng)建無加密(unencrypted)socket對象。創(chuàng)建https需要使用org.apache.http.conn.ssl.SSLConnectionSocketFactory
俏扩,PlainConnectionSocketFactory
和SSLConnectionSocketFactory
都實現(xiàn)了ConnectionSocketFactory
糜工。
好了,直接上代碼录淡,代碼實現(xiàn)的功能是捌木,組裝一個發(fā)往銀聯(lián)的查詢報文(查詢交易結(jié)果)。
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
/**
* This example demonstrates how to create secure connections with a custom SSL
* context.
*/
public class ClientCustomSSL {
private static String reqStr = "txnType=00&signMethod=01&certId=68759663125&encoding=UTF-8&merId=777290058110048&bizType=000201&txnSubType=00&signature=k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D&orderId=20160309145206&version=5.0.0&txnTime=20160309145206&accessType=0";
private static String url = "https://101.231.204.80:5000/gateway/api/queryTrans.do";
// 信任管理器
private static X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
public final static void main(String[] args) throws Exception {
long starttime = System.currentTimeMillis();
SSLContext sslContext = SSLContext.getInstance("TLS");
// 初始化SSL上下文
sslContext.init(null, new TrustManager[] { tm }, null);
// SSL套接字連接工廠,NoopHostnameVerifier為信任所有服務(wù)器
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
/**
* 通過setSSLSocketFactory(sslsf)保證httpclient實例能發(fā)送Https請求
*/
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).setMaxConnTotal(50)
.setMaxConnPerRoute(50).setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(60000).setConnectTimeout(60000).setSocketTimeout(60000).build())
.build();
try {
HttpPost httppost = new HttpPost(url);
// 設(shè)置參數(shù)赁咙,參數(shù)含義不需要理解
Map<String, String> map = new HashMap<String, String>();
map.put("txnType","00");
map.put("signMethod","01");
map.put("certId","68759663125");
map.put("encoding","UTF-8");
map.put("merId","777290058110048");
map.put("bizType","000201");
map.put("txnSubType","00");
map.put("signature","k0lrWgeLK%2Fx%2B8ajj15QCYfmdQxZSKBjXUJN0bLt17rp87ptogxWgHAAq7EUt8RlEbxD6GaRngwtdLGiy6are45Gj1dBLJBtW2841WIq4Ywzx3oK6538Kfh9ll91GJcZJGYz8LuJoZfii7HFPlpl1ZsPZbbdKP6WFVHNMnGnL9nk9QSa%2BihXGpyK%2Fy1FA42AJpfc%2FTT3BV6C%2FxpoEhXzVckHnniVnCpLdGnPfZOd76wK%2Fa%2BALNmniwUZmMj9uNPwnONIIwL%2FFqrqQinQArolW%2FrcIt9NL7qKvQujM%2BdRvd1fboAHI5bZC3ktVPB0s5QFfsRhSRFghVi4RHOzL8ZG%2FVQ%3D%3D");
map.put("orderId","20160309145206");
map.put("version","5.0.0");
map.put("txnTime","20160309145206");
map.put("accessType","0");
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Entry<String, String> elem = (Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
}
if (list.size() > 0) {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, "UTF-8");
httppost.setEntity(entity);
}
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
String s = EntityUtils.toString(entity,"UTF-8");
System.out.println("應(yīng)答內(nèi)容:" + s);
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
long endtime = System.currentTimeMillis();
System.out.println("耗時:" + (endtime-starttime) + "ms");
}
}
使用注冊器可以保證既能發(fā)送http請求也能發(fā)送httpsclient請求钮莲,代碼塊如下:
int httpReqTimeOut = 60000;//60秒
SSLContext sslContext = SSLContext.getInstance("TLS");
// 初始化SSL上下文
sslContext.init(null, new TrustManager[] { tm }, null);
// SSL套接字連接工廠,NoopHostnameVerifier為信任所有服務(wù)器
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
// 注冊http套接字工廠和https套接字工廠
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build();
// 連接池管理器
PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(r);
pcm.setMaxTotal(maxConnTotal);//連接池最大連接數(shù)
pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每個路由最大連接數(shù)
/**
* 請求參數(shù)配置
* connectionRequestTimeout:
* 從連接池中獲取連接的超時時間免钻,超過該時間未拿到可用連接,
* 會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
* connectTimeout:
* 連接上服務(wù)器(握手成功)的時間崔拥,超出該時間拋出connect timeout
* socketTimeout:
* 服務(wù)器返回數(shù)據(jù)(response)的時間极舔,超過該時間拋出read timeout
*/
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(httpReqTimeOut)
.setConnectTimeout(httpReqTimeOut)
.setSocketTimeout(httpReqTimeOut)
.build();
/**
* 構(gòu)造closeableHttpClient對象
*/
closeableHttpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(pcm)
.setRetryHandler(retryHandler)
.build();
關(guān)鍵代碼為:
// 注冊http套接字工廠和https套接字工廠
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build();