天天看點

HttpClient-4.5總結(4)

接着 上一篇

,總結一下HttpClient發送https請求相關的内容。

先簡單介紹連接配接工廠(

interface org.apache.http.conn.socket.ConnectionSocketFactory

),連接配接工廠主要用于建立、初始化、連接配接socket。

org.apache.http.conn.socket.PlainConnectionSocketFactory

是預設的socket工廠,用于建立無加密(unencrypted)socket對象。建立https需要使用

org.apache.http.conn.ssl.SSLConnectionSocketFactory

PlainConnectionSocketFactory

SSLConnectionSocketFactory

都實作了

ConnectionSocketFactory

好了,直接上代碼,代碼實作的功能是,組裝一個發往銀聯的查詢封包(查詢交易結果)。

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為信任所有伺服器
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,NoopHostnameVerifier.INSTANCE);
        /**
         * 通過setSSLSocketFactory(sslsf)保證httpclient執行個體能發送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);
            
            // 設定參數,參數含義不需要了解
            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("應答内容:" + s);
                
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        
        long endtime = System.currentTimeMillis();
        System.out.println("耗時:" + (endtime-starttime) + "ms");
    }

}
           

使用注冊器可以保證既能發送http請求也能發送httpsclient請求,代碼塊如下:

int httpReqTimeOut = 60000;//60秒

SSLContext sslContext = SSLContext.getInstance("TLS");
        // 初始化SSL上下文
        sslContext.init(null, new TrustManager[] { tm }, null);
        // SSL套接字連接配接工廠,NoopHostnameVerifier為信任所有伺服器
        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);//連接配接池最大連接配接數
        pcm.setDefaultMaxPerRoute(maxConnPerRoute);//每個路由最大連接配接數
        /**
         *  請求參數配置
         *  connectionRequestTimeout:
         *                          從連接配接池中擷取連接配接的逾時時間,超過該時間未拿到可用連接配接,
         *                          會抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
         *  connectTimeout:
         *                  連接配接上伺服器(握手成功)的時間,超出該時間抛出connect timeout
         *  socketTimeout:
         *                  伺服器傳回資料(response)的時間,超過該時間抛出read timeout
         */
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(httpReqTimeOut)
                .setConnectTimeout(httpReqTimeOut)
                .setSocketTimeout(httpReqTimeOut)
                .build();
        /**
         * 構造closeableHttpClient對象
         */
        closeableHttpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pcm)
                .setRetryHandler(retryHandler)
                .build();
           

關鍵代碼為:

// 注冊http套接字工廠和https套接字工廠
        Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", sslsf)
                .build();
           

繼續閱讀