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