1. 程式人生 > >httpclient傳送https請求在weblogic上效率低下問題

httpclient傳送https請求在weblogic上效率低下問題

最近遇到一個比較詭異的問題:
一個數據供應商的請求連結是https的,於是在網路上搜索了一個httpclient傳送https請求的方法,能夠成功返回資料,但是耗時非常長大概要17~18秒。在排除網路環境、伺服器、資料庫等影響因素後,發現罪魁禍首就在這了。(httpclient的版本是4.3.4)
程式碼如下:

import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import
org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.impl.client.DefaultHttpClient; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; public
class SSLClient extends DefaultHttpClient { public SSLClient() throws Exception{ super(); SSLContext ctx = SSLContext.getInstance("TLS"); 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; } }; ctx.init(null, new TrustManager[]{tm}, null); SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = this.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", 443, ssf)); } } import com.google.common.base.Charsets; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpClientUtil { public static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); public static String doPost(String url, String json) { HttpClient httpClient; HttpPost httpPost; String result = null; try { httpClient = new SSLClient(); httpPost = new HttpPost(url); StringEntity entity = new StringEntity(json, Charsets.UTF_8);//解決中文亂碼問題 entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); HttpResponse response = httpClient.execute(httpPost); if (response != null) { HttpEntity resEntity = response.getEntity(); if (resEntity != null) { result = EntityUtils.toString(resEntity, Charsets.UTF_8); } } } catch (Exception e) { logger.error("呼叫訪問https工具類, 拋錯:", e); } return result; } } public static String doGet(String url, String json) { HttpClient httpClient; HttpGet httpGet; String result = null; try { httpClient = new SSLClient(); httpGet= new HttpGet(url); StringEntity entity = new StringEntity(json, Charsets.UTF_8);//解決中文亂碼問題 entity.setContentEncoding("UTF-8"); entity.setContentType("application/json"); httpPost.setEntity(entity); HttpResponse response = httpClient.execute(HttpGet ); if (response != null) { HttpEntity resEntity = response.getEntity(); if (resEntity != null) { result = EntityUtils.toString(resEntity, Charsets.UTF_8); } } } catch (Exception e) { logger.error("呼叫訪問https工具類, 拋錯:", e); } return result; }

為了解決這個問題決定拋棄HttpClient,在網上搜索了很多資料,終於找到一個靠譜的方法。程式碼如下

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import com.alibaba.fastjson.JSONObject;

/**
 * Http請求
 * @author mszhou
 *
 */
public class HTTPUtils {
    private static final int TIMEOUT = 45000;
    public static final String ENCODING = "UTF-8";

    /**
     * 建立HTTP連線
     * 
     * @param url
     *            地址
     * @param method
     *            方法
     * @param headerParameters
     *            頭資訊
     * @param body
     *            請求內容
     * @return
     * @throws Exception
     */
    private static HttpURLConnection createConnection(String url,
            String method, Map<String, String> headerParameters, String body)
            throws Exception {
            //這裡原來是URL Url = new URL(url),因為要部署到weblogic上所以要這麼修改,請小夥伴沒看情況修改。不知道為什麼要這麼該的話,請百度一下
        URL Url = new URL(null,url,new sun.net.www.protocol.https.handler());
        trustAllHttpsCertificates();
        HttpURLConnection httpConnection = (HttpURLConnection) Url
                .openConnection();
        // 設定請求時間
        httpConnection.setConnectTimeout(TIMEOUT);
        // 設定 header
        if (headerParameters != null) {
            Iterator<String> iteratorHeader = headerParameters.keySet()
                    .iterator();
            while (iteratorHeader.hasNext()) {
                String key = iteratorHeader.next();
                httpConnection.setRequestProperty(key,
                        headerParameters.get(key));
            }
        }
        httpConnection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded;charset=" + ENCODING);

        // 設定請求方法
        httpConnection.setRequestMethod(method);
        httpConnection.setDoOutput(true);
        httpConnection.setDoInput(true);
        // 寫query資料流
        if (!(body == null || body.trim().equals(""))) {
            OutputStream writer = httpConnection.getOutputStream();
            try {
                writer.write(body.getBytes(ENCODING));
            } finally {
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
            }
        }

        // 請求結果
        int responseCode = httpConnection.getResponseCode();
        if (responseCode != 200) {
            throw new Exception(responseCode
                    + ":"
                    + inputStream2String(httpConnection.getErrorStream(),
                            ENCODING));
        }

        return httpConnection;
    }

    /**
     * POST請求
     * @param address 請求地址
     * @param headerParameters 引數
     * @param body
     * @return
     * @throws Exception
     */
    public static String post(String address,
            Map<String, String> headerParameters, String body) throws Exception {

        return proxyHttpRequest(address, "POST", null,
                getRequestBody(headerParameters));
    }

    /**
     * GET請求
     * @param address
     * @param headerParameters
     * @param body
     * @return
     * @throws Exception
     */
    public static String get(String address,
            Map<String, String> headerParameters, String body) throws Exception {

        return proxyHttpRequest(address + "?"
                + getRequestBody(headerParameters), "GET", null, null);
    }

    /**
     * 讀取網路檔案
     * @param address
     * @param headerParameters
     * @param body
     * @param file
     * @return
     * @throws Exception
     */
    public static String getFile(String address,
            Map<String, String> headerParameters, File file) throws Exception {
        String result = "fail";

        HttpURLConnection httpConnection = null;
        try {
            httpConnection = createConnection(address, "POST", null,
                    getRequestBody(headerParameters));
            result = readInputStream(httpConnection.getInputStream(), file);

        } catch (Exception e) {
            throw e;
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }

        }

        return result;
    }

    public static byte[] getFileByte(String address,
            Map<String, String> headerParameters) throws Exception {
        byte[] result = null;

        HttpURLConnection httpConnection = null;
        try {
            httpConnection = createConnection(address, "POST", null,
                    getRequestBody(headerParameters));
            result = readInputStreamToByte(httpConnection.getInputStream());

        } catch (Exception e) {
            throw e;
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }

        }

        return result;
    }

    /**
     * 讀取檔案流
     * @param in
     * @return
     * @throws Exception
     */
    public static String readInputStream(InputStream in, File file)
            throws Exception {
        FileOutputStream out = null;
        ByteArrayOutputStream output = null;

        try {
            output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                output.write(buffer, 0, len);
            }

            out = new FileOutputStream(file);
            out.write(output.toByteArray());

        } catch (Exception e) {
            throw e;
        } finally {
            if (output != null) {
                output.close();
            }
            if (out != null) {
                out.close();
            }
        }
        return "success";
    }

    public static byte[] readInputStreamToByte(InputStream in) throws Exception {
        FileOutputStream out = null;
        ByteArrayOutputStream output = null;
        byte[] byteFile = null;

        try {
            output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                output.write(buffer, 0, len);
            }
            byteFile = output.toByteArray();
        } catch (Exception e) {
            throw e;
        } finally {
            if (output != null) {
                output.close();
            }
            if (out != null) {
                out.close();
            }
        }

        return byteFile;
    }

    /**
     * HTTP請求
     * 
     * @param address
     *            地址
     * @param method
     *            方法
     * @param headerParameters
     *            頭資訊
     * @param body
     *            請求內容
     * @return
     * @throws Exception
     */
    public static String proxyHttpRequest(String address, String method,
            Map<String, String> headerParameters, String body) throws Exception {
        String result = null;
        HttpURLConnection httpConnection = null;

        try {
            httpConnection = createConnection(address, method,
                    headerParameters, body);

            String encoding = "UTF-8";
            if (httpConnection.getContentType() != null
                    && httpConnection.getContentType().indexOf("charset=") >= 0) {
                encoding = httpConnection.getContentType()
                        .substring(
                                httpConnection.getContentType().indexOf(
                                        "charset=") + 8);
            }
            result = inputStream2String(httpConnection.getInputStream(),
                    encoding);
            // logger.info("HTTPproxy response: {},{}", address,
            // result.toString());

        } catch (Exception e) {
            // logger.info("HTTPproxy error: {}", e.getMessage());
            throw e;
        } finally {
            if (httpConnection != null) {
                httpConnection.disconnect();
            }
        }
        return result;
    }

    /**
     * 將引數化為 body
     * @param params
     * @return
     */
    public static String getRequestBody(Map<String, String> params) {
        return getRequestBody(params, true);
    }

    /**
     * 將引數化為 body
     * @param params
     * @return
     */
    public static String getRequestBody(Map<String, String> params,
            boolean urlEncode) {
        StringBuilder body = new StringBuilder();

        Iterator<String> iteratorHeader = params.keySet().iterator();
        while (iteratorHeader.hasNext()) {
            String key = iteratorHeader.next();
            String value = params.get(key);

            if (urlEncode) {
                try {
                    body.append(key + "=" + URLEncoder.encode(value, ENCODING)
                            + "&");
                } catch (UnsupportedEncodingException e) {
                    // e.printStackTrace();
                }
            } else {
                body.append(key + "=" + value + "&");
            }
        }

        if (body.length() == 0) {
            return "";
        }
        return body.substring(0, body.length() - 1);
    }

    /**
     * 讀取inputStream 到 string
     * @param input
     * @param encoding
     * @return
     * @throws IOException
     */
    private static String inputStream2String(InputStream input, String encoding)
            throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(input,
                encoding));
        StringBuilder result = new StringBuilder();
        String temp = null;
        while ((temp = reader.readLine()) != null) {
            result.append(temp);
        }

        return result.toString();

    }


    /**
     * 設定 https 請求
     * @throws Exception
     */
    private static void trustAllHttpsCertificates() throws Exception {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String str, SSLSession session) {
                return true;
            }
        });
        javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
        javax.net.ssl.TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
                .getInstance("TLS"); //這裡原來是SSL後來改成TLS,小夥伴們請看測試情況修改
        sc.init(null, trustAllCerts, null);
        javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
                .getSocketFactory());
    }


    //設定 https 請求證書
    static class miTM implements javax.net.ssl.TrustManager,javax.net.ssl.X509TrustManager {

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(
                java.security.cert.X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType)
                throws java.security.cert.CertificateException {
            return;
        }


    }


    //============================= 測試呼叫 

    public static void main(String[] args) {

            try {

                //請求地址(我這裡測試使用淘寶提供的手機號碼資訊查詢的介面)
                String address = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm";

                //請求引數
                Map<String, String> params = new HashMap<String, String>();
                params.put("tel", "13777777777");//這是該介面需要的引數

                // 呼叫 get 請求
                String res = get(address, params, null);
                System.out.println(res);//列印返回引數

                res = res.substring(res.indexOf("{"));//擷取
                JSONObject result = JSONObject.parseObject(res);//轉JSON

                System.out.println(result.toString());//列印

            } catch (Exception e) {
                // TODO 異常
                e.printStackTrace();
            }

    }

}

經測試,新方法雖然又臭又長,但是響應時間基本在500毫秒以下,完全滿足需求。

問題是:httpclient為什麼效率低下?原理不是一樣的嗎?跪求老司機科普!!

相關推薦

httpclient傳送https請求weblogic效率低下問題

最近遇到一個比較詭異的問題: 一個數據供應商的請求連結是https的,於是在網路上搜索了一個httpclient傳送https請求的方法,能夠成功返回資料,但是耗時非常長大概要17~18秒。在排除網路環境、伺服器、資料庫等影響因素後,發現罪魁禍首就在這了。(h

httpClient傳送https請求程式碼

package com.lvmama.dest.dianping; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SS

使用HttpClient傳送HttpPost請求包含傳本地圖片和遠端圖片的傳輸實現

在實際專案中需要在當前系統中模擬瀏覽器傳送一個post請求,正常情況下傳文字沒多大問題,但是如果帶上傳檔案功能的話, 網上的資料不太好找,好在經過我多方尋找,加上自由發揮,真讓我搞出來了。 下面程式碼為核心程式碼, 可以上傳  File物件, 轉換成byte

使用HttpClient傳送https請求GET方式

第一步:封裝查詢引數,拼接url String url = "www.baidu.com?name=liufei";第二步:發出請求 HttpClient client = new DefaultHttpClient(); HttpGet request = new H

httpClient傳送https請求

前言       我們知道現在的http請求應用的越來越廣泛,最常見的場景就是瀏覽器作為http請求的客戶端,請求http服務端。在瀏覽器傳送請求時,會封裝請求行,請求頭,請求體資訊,那我們在用java程式碼模擬時,也需要帶上http請求的這些相關資訊。java自帶的java

HTTPClient 傳送HTTPS請求

HTTPClient 傳送HTTP請求就不多說了, 現在給出傳送HTTPS請求, 主要思路是忽略證書驗證. /** * * @param url * @param contextType "image/jpeg","application/Json" *

使用Httpclient(post請求傳檔案及其他引數到https協議的伺服器

最近有一個需求要用到httpclient大概如下:    運用httpclient傳送請求到一個https的伺服器,其中一個引數就是一個xml檔案,也就是需要把檔案傳上去, 而且有其他的引數,如果用普

weblogic傳送https請求的證書錯誤的解決辦法

問題原因:部署後,使用了Weblogic的jar包,導致報錯(誰不知道啊...)。至於哪個jar包,我真不知道了。把報錯的weblogic相關路徑往瀏覽器一貼。有如下答案http://blog.csdn.net/u014520797/article/details/50263089 。這哥們讓我配置webl

java中使用Apache HttpClient傳送Http請求,並獲取返回結果

傳送http請求可以寫成一個工具類,HttpClient可以使用連線池建立,這樣的好處是我們可以自己定義一些配置,比如請求超時時間,最大連線數等等。 public class HttpUtil { private static CloseableHttpClient http

httpClient傳送post請求的demo

/** * 傳送HttpClient * */ public class HttpClientTest { public static void main(String[] args) throws IOException { delete(); } public st

java實現httpclient傳送post請求

需求:現在要在java後端介面中直接請求客戶提供的其他介面來獲取所需要的資料,那麼就需要用到httpclient來做,下面做一個實現以記錄... 第一步:匯入所需要的jar包並寫一個工具類 1.post請求工具類 因為我們需要的協議是https協議,所以我做了

【封裝】使用okHttp傳送網路請求傳下載進度監聽

參考資料: 如何正確地寫出單例模式 http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern 設計模式總結篇系列:單例模式(SingleTon) htt

關於java傳送https請求 提示java.security.cert.CertificateException: No name matching xxxx found的解決方法

1.這2天專案中需要呼叫外部介面,開始以為挺簡單的,後面使用HttpConnection傳送post請求出現了以下的錯誤資訊.通過觀察日誌中的錯誤資訊發現,應該是在建立HttpConnection的http連線的時候,出現了SSL安全認證的問題,通過查詢相關的資

HttpClient傳送post請求帶引數例項

本例子跟上篇的get請求功能一致,只是換用了不同的請求例項,前端請求 var jsonParam = { title : title, partPath : partPath, modelId : modelId, exportTemplate : exportTempl

Qt 執行緒中使用httpclient傳送 post 請求

QT 5.92 (1) 在建構函式中初始化QNetworkAccessManager m_manager = new QNetworkAccessManager(); (2) 執行緒啟動之前繫結訊號和槽 QEventLoop temp_loop; connect(m_manager, SIG

HttpClient 傳送 POST 請求

##API 說明 HttpClientBuilder用於建立CloseableHttpClient例項。 在 HttpClient 新的版本中, AbstractHttpClient、 AutoRetryHttpClient、 DefaultHttpClient

Java工具類--通過HttpClient傳送http請求

在寫網路程式的時候,經常會有從網址獲取資料的需求,上一篇解析JSON就需要從百度獲取天氣資料,本文介紹一種Java傳送http請求的工具–HttpClient。 ##HttpClient的介紹 The most essential function of Ht

利用HttpClient傳送post請求京東介面並將結果用POI匯出為 Excel表格

package com.zhongsou.demo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.Fil

HttpClient傳送Request請求

HttpClient httpclient = new DefaultHttpClient(); InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(reqXM

Java 傳送http請求傳檔案

package wxapi.WxHelper; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.F