<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ? ? ?版權聲明:本文為博主原創文章,未經博主允許不得轉載。如需轉載請聲明:【轉自 http://blog.csdn.net/xiaoxian8023 】 ? ? ?上一篇文章中,簡單分享一下封裝HttpClient工具類的思路及部分代碼,本文將分享如何實現插件式配置HttpClient對象。 ? ? ?如果你看過我前面的幾篇關于HttpClient的文章或者官網示例,應該都知道HttpClient對象在創建時,都可以設置各種參數,但是卻沒有簡單的進行封裝,比如對我來說比較重要的3個:代理、ssl(包含繞過證書驗證和自定義證書驗證)、超時。還需要自己寫。所以這里我就簡單封裝了一下,順便還封裝了一個連接池的配置。 ? ? ?其實說是插件式配置,那是高大上的說法,說白了,就是采用了建造者模式來創建HttpClient對象(級聯調用)。HttpClient的jar包中提供了一個創建HttpClient對象的類HttpClientBuilder。所以我是創建該類的子類HCB,然后做了一些改動。每個配置方法的返回值都是HCB,這樣就支持級聯調用了。具體代碼如下: ~~~ package com.tgb.ccl.http.httpclient.builder; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; 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.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import com.tgb.ccl.http.common.SSLs; import com.tgb.ccl.http.exception.HttpProcessException; /** * httpclient創建者 * * @author arron * @date 2015年11月9日 下午5:45:47 * @version 1.0 */ public class HCB extends HttpClientBuilder{ private boolean isSetPool=false;//記錄是否設置了連接池 private boolean isNewSSL=false;//記錄是否設置了更新了ssl //用于配置ssl private SSLs ssls = SSLs.getInstance(); private HCB(){} public static HCB custom(){ return new HCB(); } /** * 設置超時時間 * * @param timeout 超市時間,單位-毫秒 * @return */ public HCB timeout(int timeout){ // 配置請求的超時設置 RequestConfig config = RequestConfig.custom() .setConnectionRequestTimeout(timeout) .setConnectTimeout(timeout) .setSocketTimeout(timeout) .build(); return (HCB) this.setDefaultRequestConfig(config); } /** * 設置ssl安全鏈接 * * @return * @throws HttpProcessException */ public HCB ssl() throws HttpProcessException { if(isSetPool){//如果已經設置過線程池,那肯定也就是https鏈接了 if(isNewSSL){ throw new HttpProcessException("請先設置ssl,后設置pool"); } return this; } Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder .<ConnectionSocketFactory> create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", ssls.getSSLCONNSF()).build(); //設置連接池大小 PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); return (HCB) this.setConnectionManager(connManager); } /** * 設置自定義sslcontext * * @param keyStorePath 密鑰庫路徑 * @return * @throws HttpProcessException */ public HCB ssl(String keyStorePath) throws HttpProcessException{ return ssl(keyStorePath,"nopassword"); } /** * 設置自定義sslcontext * * @param keyStorePath 密鑰庫路徑 * @param keyStorepass 密鑰庫密碼 * @return * @throws HttpProcessException */ public HCB ssl(String keyStorePath, String keyStorepass) throws HttpProcessException{ this.ssls = SSLs.custom().customSSL(keyStorePath, keyStorepass); this.isNewSSL=true; return ssl(); } /** * 設置連接池(默認開啟https) * * @param maxTotal 最大連接數 * @param defaultMaxPerRoute 每個路由默認連接數 * @return * @throws HttpProcessException */ public HCB pool(int maxTotal, int defaultMaxPerRoute) throws HttpProcessException{ Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder .<ConnectionSocketFactory> create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", ssls.getSSLCONNSF()).build(); //設置連接池大小 PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); connManager.setMaxTotal(maxTotal); connManager.setDefaultMaxPerRoute(defaultMaxPerRoute); isSetPool=true; return (HCB) this.setConnectionManager(connManager); } /** * 設置代理 * * @param hostOrIP 代理host或者ip * @param port 代理端口 * @return */ public HCB proxy(String hostOrIP, int port){ // 依次是代理地址,代理端口號,協議類型 HttpHost proxy = new HttpHost(hostOrIP, port, "http"); DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); return (HCB) this.setRoutePlanner(routePlanner); } } ~~~ ? ? ?大家可以看到,這個有成員變量,而且不是static類型,所以是非線程安全的。所以我為了方便使用,就效仿HttpClients(其custom方法可以創建HttpClientBuilder實例)寫了一個靜態的custom方法,來返回一個新的HCB實例。將構造方法設置成了private,無法通過new的方式創建實例,所以只能通過custom方法來創建。在想生成HttpClient對象的時候,調用一下build方法就可以了。于是乎就出現了這樣簡單、方便又明了的調用方式: ~~~ HttpClient client = HCB.custom().timeout(10000).proxy("127.0.0.1", 8087).ssl("D:\\keys\\wsriakey","tomcat").build(); ~~~ ? ? ?說到ssl,還需要另外一個封裝的類,為了其他工具類有可能也會用到ssl,所以就單出來了。不多解釋,直接上代碼: ~~~ /** * 設置ssl * * @author arron * @date 2015年11月3日 下午3:11:54 * @version 1.0 */ public class SSLs { private static final SSLHandler simpleVerifier = new SSLHandler(); private static SSLConnectionSocketFactory sslConnFactory ; private static SSLs sslutil = new SSLs(); private SSLContext sc; public static SSLs getInstance(){ return sslutil; } public static SSLs custom(){ return new SSLs(); } // 重寫X509TrustManager類的三個方法,信任服務器證書 private static class SSLHandler implements X509TrustManager, HostnameVerifier{ @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException { } @Override public boolean verify(String paramString, SSLSession paramSSLSession) { return true; } }; // 信任主機 public static HostnameVerifier getVerifier() { return simpleVerifier; } public synchronized SSLConnectionSocketFactory getSSLCONNSF() throws HttpProcessException { if (sslConnFactory != null) return sslConnFactory; try { SSLContext sc = getSSLContext(); sc.init(null, new TrustManager[] { simpleVerifier }, null); sslConnFactory = new SSLConnectionSocketFactory(sc, simpleVerifier); } catch (KeyManagementException e) { throw new HttpProcessException(e); } return sslConnFactory; } public SSLs customSSL(String keyStorePath, String keyStorepass) throws HttpProcessException{ FileInputStream instream =null; KeyStore trustStore = null; try { trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); instream = new FileInputStream(new File(keyStorePath)); trustStore.load(instream, keyStorepass.toCharArray()); // 相信自己的CA和所有自簽名的證書 sc= SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) .build(); } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | KeyManagementException e) { throw new HttpProcessException(e); }finally{ try { instream.close(); } catch (IOException e) {} } return this; } public SSLContext getSSLContext() throws HttpProcessException{ try { if(sc==null){ sc = SSLContext.getInstance("SSLv3"); } return sc; } catch (NoSuchAlgorithmException e) { throw new HttpProcessException(e); } } } ~~~ ? ? ?基本上就是這樣了。在上一篇中遺留了一個小問題,正好在這里說一下。上一篇文中說道提供一個默認的HttpClient實現,其實是2個,分別針對于http和https。方便調用。具體代碼如下: ~~~ //默認采用的http協議的HttpClient對象 private static HttpClient client4HTTP; //默認采用的https協議的HttpClient對象 private static HttpClient client4HTTPS; static{ try { client4HTTP = HCB.custom().build(); client4HTTPS = HCB.custom().ssl().build(); } catch (HttpProcessException e) { logger.error("創建https協議的HttpClient對象出錯:{}", e); } } /** * 判斷url是http還是https,直接返回相應的默認client對象 * * @return 返回對應默認的client對象 * @throws HttpProcessException */ private static HttpClient create(String url) throws HttpProcessException { if(url.toLowerCase().startsWith("https://")){ return client4HTTPS; }else{ return client4HTTP; } } ~~~ ? ? ?這樣在使用工具類的時候,如果不需要自定義HttpClient時,就直接用下面的方式調用: ~~~ public static void testSimple() throws HttpProcessException{ String url = "http://tool.oschina.net/"; //簡單調用 String resp = HttpClientUtil.send(url); System.out.println("請求結果內容長度:"+ resp); } ~~~ ? ? ?好了,插件化配置HttpClient,就是這些內容,在下一篇文章中分享如何插件式配置Header。沒錯,思路還是跟本文一樣。敬請期待吧。 ? ? ?代碼已上傳至:[https://github.com/Arronlong/httpclientUtil](https://github.com/Arronlong/httpclientUtil)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看