原文:https://blog.csdn.net/fengshizty/article/details/53100694
Http和https網絡請求
主要總結一下使用到的網絡請求框架,一種是同步網絡請求org.apache.httpcomponents的httpclient,另一種是異步網絡請求com.ning的async-http-client,總結一下常用的http請求方式封裝使用,如post、get、put、delete等,以及涉及到ssl證書https請求的雙向證書驗證。
一、apache同步請求httpclient
1、引入文件
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>4.5.2</version>
- </dependency>
2、http和https的方法封裝
涉及常用的post和get的請求,https的ssl雙向證書驗證。
- import java.io.IOException;
- import java.io.UnsupportedEncodingException;
- import java.net.URLEncoder;
- import java.security.KeyStore;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Map;
- import java.util.Map.Entry;
- import javax.net.ssl.SSLContext;
- 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.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
- import org.apache.http.entity.StringEntity;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.message.BasicNameValuePair;
- import org.apache.http.ssl.SSLContexts;
- import org.apache.http.util.EntityUtils;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- /**
- * 創建時間:2016年11月9日 下午4:16:32
- *
- * @author andy
- * @version 2.2
- */
- public class HttpUtils {
- private static final String DEFAULT_CHARSET = "UTF-8";
- private static final int CONNECT_TIME_OUT = 5000; //鏈接超時時間3秒
- private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build();
- private static SSLContext wx_ssl_context = null; //微信支付ssl證書
- static{
- Resource resource = new ClassPathResource("wx_apiclient_cert.p12");
- try {
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- char[] keyPassword = ConfigUtil.getProperty("wx.mchid").toCharArray(); //證書密碼
- keystore.load(resource.getInputStream(), keyPassword);
- wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @param params 參數
- * @param headers headers參數
- * @return 請求失敗返回null
- */
- public static String get(String url, Map<String, String> params, Map<String, String> headers) {
- CloseableHttpClient httpClient = null;
- if (params != null && !params.isEmpty()) {
- StringBuffer param = new StringBuffer();
- boolean flag = true; // 是否開始
- for (Entry<String, String> entry : params.entrySet()) {
- if (flag) {
- param.append("?");
- flag = false;
- } else {
- param.append("&");
- }
- param.append(entry.getKey()).append("=");
- try {
- param.append(URLEncoder.encode(entry.getValue(), DEFAULT_CHARSET));
- } catch (UnsupportedEncodingException e) {
- //編碼失敗
- }
- }
- url += param.toString();
- }
- String body = null;
- CloseableHttpResponse response = null;
- try {
- httpClient = HttpClients.custom()
- .setDefaultRequestConfig(REQUEST_CONFIG)
- .build();
- HttpGet httpGet = new HttpGet(url);
- response = httpClient.execute(httpGet);
- body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (response != null) {
- try {
- response.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (httpClient != null) {
- try {
- httpClient.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return body;
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @return 請求失敗返回null
- */
- public static String get(String url) {
- return get(url, null);
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String get(String url, Map<String, String> params) {
- return get(url, params, null);
- }
- /**
- * @description 功能描述: post 請求
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String post(String url, Map<String, String> params) {
- CloseableHttpClient httpClient = null;
- HttpPost httpPost = new HttpPost(url);
- List<NameValuePair> nameValuePairs = new ArrayList<>();
- if (params != null && !params.isEmpty()) {
- for (Entry<String, String> entry : params.entrySet()) {
- nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
- }
- }
- String body = null;
- CloseableHttpResponse response = null;
- try {
- httpClient = HttpClients.custom()
- .setDefaultRequestConfig(REQUEST_CONFIG)
- .build();
- httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
- response = httpClient.execute(httpPost);
- body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (response != null) {
- try {
- response.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (httpClient != null) {
- try {
- httpClient.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return body;
- }
- /**
- * @description 功能描述: post 請求
- * @param url 請求地址
- * @param s 參數xml
- * @return 請求失敗返回null
- */
- public static String post(String url, String s) {
- CloseableHttpClient httpClient = null;
- HttpPost httpPost = new HttpPost(url);
- String body = null;
- CloseableHttpResponse response = null;
- try {
- httpClient = HttpClients.custom()
- .setDefaultRequestConfig(REQUEST_CONFIG)
- .build();
- httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));
- response = httpClient.execute(httpPost);
- body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (response != null) {
- try {
- response.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (httpClient != null) {
- try {
- httpClient.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return body;
- }
- /**
- * @description 功能描述: post https請求,服務器雙向證書驗證
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String posts(String url, Map<String, String> params) {
- CloseableHttpClient httpClient = null;
- HttpPost httpPost = new HttpPost(url);
- List<NameValuePair> nameValuePairs = new ArrayList<>();
- if (params != null && !params.isEmpty()) {
- for (Entry<String, String> entry : params.entrySet()) {
- nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
- }
- }
- String body = null;
- CloseableHttpResponse response = null;
- try {
- httpClient = HttpClients.custom()
- .setDefaultRequestConfig(REQUEST_CONFIG)
- .setSSLSocketFactory(getSSLConnectionSocket())
- .build();
- httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
- response = httpClient.execute(httpPost);
- body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (response != null) {
- try {
- response.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (httpClient != null) {
- try {
- httpClient.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return body;
- }
- /**
- * @description 功能描述: post https請求,服務器雙向證書驗證
- * @param url 請求地址
- * @param s 參數xml
- * @return 請求失敗返回null
- */
- public static String posts(String url, String s) {
- CloseableHttpClient httpClient = null;
- HttpPost httpPost = new HttpPost(url);
- String body = null;
- CloseableHttpResponse response = null;
- try {
- httpClient = HttpClients.custom()
- .setDefaultRequestConfig(REQUEST_CONFIG)
- .setSSLSocketFactory(getSSLConnectionSocket())
- .build();
- httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));
- response = httpClient.execute(httpPost);
- body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (response != null) {
- try {
- response.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (httpClient != null) {
- try {
- httpClient.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return body;
- }
- //獲取ssl connection鏈接
- private static SSLConnectionSocketFactory getSSLConnectionSocket() {
- return new SSLConnectionSocketFactory(wx_ssl_context, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}, null,
- SSLConnectionSocketFactory.getDefaultHostnameVerifier());
- }
- }
二、com.ning異步請求async-http-client
1、引入文件
- <dependency>
- <groupId>com.ning</groupId>
- <artifactId>async-http-client</artifactId>
- <version>1.9.40</version>
- </dependency>
2、http和https的方法封裝
涉及常用的post和get的請求,https的ssl雙向證書驗證。
- import java.security.KeyStore;
- import java.security.SecureRandom;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.Future;
- import javax.net.ssl.KeyManagerFactory;
- import javax.net.ssl.SSLContext;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- import com.ning.http.client.AsyncHttpClient;
- import com.ning.http.client.AsyncHttpClientConfig;
- import com.ning.http.client.Response;
- /**
- * 創建時間:2016年11月8日 下午5:16:32
- *
- * @author andy
- * @version 2.2
- */
- public class HttpKit {
- private static final String DEFAULT_CHARSET = "UTF-8";
- private static final int CONNECT_TIME_OUT = 5000; //鏈接超時時間3秒
- private static SSLContext wx_ssl_context = null; //微信支付ssl證書
- static{
- Resource resource = new ClassPathResource("wx_apiclient_cert.p12"); //獲取微信證書 或者直接從文件流讀取
- char[] keyStorePassword = ConfigUtil.getProperty("wx.mchid").toCharArray(); //證書密碼
- try {
- KeyStore keystore = KeyStore.getInstance("PKCS12");
- keystore.load(resource.getInputStream(), keyStorePassword);
- KeyManagerFactory keyManagerFactory = KeyManagerFactory
- .getInstance(KeyManagerFactory.getDefaultAlgorithm());
- keyManagerFactory.init(keystore, keyStorePassword);
- SSLContext wx_ssl_context = SSLContext.getInstance("TLS");
- wx_ssl_context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @param params 參數
- * @param headers headers參數
- * @return 請求失敗返回null
- */
- public static String get(String url, Map<String, String> params, Map<String, String> headers) {
- AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()
- .setConnectTimeout(CONNECT_TIME_OUT).build());
- AsyncHttpClient.BoundRequestBuilder builder = http.prepareGet(url);
- builder.setBodyEncoding(DEFAULT_CHARSET);
- if (params != null && !params.isEmpty()) {
- Set<String> keys = params.keySet();
- for (String key : keys) {
- builder.addQueryParam(key, params.get(key));
- }
- }
- if (headers != null && !headers.isEmpty()) {
- Set<String> keys = headers.keySet();
- for (String key : keys) {
- builder.addHeader(key, params.get(key));
- }
- }
- Future<Response> f = builder.execute();
- String body = null;
- try {
- body = f.get().getResponseBody(DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- }
- http.close();
- return body;
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @return 請求失敗返回null
- */
- public static String get(String url) {
- return get(url, null);
- }
- /**
- * @description 功能描述: get 請求
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String get(String url, Map<String, String> params) {
- return get(url, params, null);
- }
- /**
- * @description 功能描述: post 請求
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String post(String url, Map<String, String> params) {
- AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()
- .setConnectTimeout(CONNECT_TIME_OUT).build());
- AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
- builder.setBodyEncoding(DEFAULT_CHARSET);
- if (params != null && !params.isEmpty()) {
- Set<String> keys = params.keySet();
- for (String key : keys) {
- builder.addQueryParam(key, params.get(key));
- }
- }
- Future<Response> f = builder.execute();
- String body = null;
- try {
- body = f.get().getResponseBody(DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- }
- http.close();
- return body;
- }
- /**
- * @description 功能描述: post 請求
- * @param url 請求地址
- * @param s 參數xml
- * @return 請求失敗返回null
- */
- public static String post(String url, String s) {
- AsyncHttpClient http = new AsyncHttpClient(new AsyncHttpClientConfig.Builder()
- .setConnectTimeout(CONNECT_TIME_OUT).build());
- AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
- builder.setBodyEncoding(DEFAULT_CHARSET);
- builder.setBody(s);
- Future<Response> f = builder.execute();
- String body = null;
- try {
- body = f.get().getResponseBody(DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- }
- http.close();
- return body;
- }
- /**
- * @description 功能描述: post https請求,服務器雙向證書驗證
- * @param url 請求地址
- * @param params 參數
- * @return 請求失敗返回null
- */
- public static String posts(String url, Map<String, String> params){
- AsyncHttpClient http = new AsyncHttpClient(
- new AsyncHttpClientConfig.Builder()
- .setConnectTimeout(CONNECT_TIME_OUT)
- .setSSLContext(wx_ssl_context)
- .build());
- AsyncHttpClient.BoundRequestBuilder bbuilder = http.preparePost(url);
- bbuilder.setBodyEncoding(DEFAULT_CHARSET);
- if (params != null && !params.isEmpty()) {
- Set<String> keys = params.keySet();
- for (String key : keys) {
- bbuilder.addQueryParam(key, params.get(key));
- }
- }
- Future<Response> f = bbuilder.execute();
- String body = null;
- try {
- body = f.get().getResponseBody(DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- }
- http.close();
- return body;
- }
- /**
- * @description 功能描述: post https請求,服務器雙向證書驗證
- * @param url 請求地址
- * @param s 參數xml
- * @return 請求失敗返回null
- */
- public static String posts(String url, String s) {
- AsyncHttpClient http = new AsyncHttpClient(
- new AsyncHttpClientConfig.Builder()
- .setConnectTimeout(CONNECT_TIME_OUT)
- .setSSLContext(wx_ssl_context).build());
- AsyncHttpClient.BoundRequestBuilder builder = http.preparePost(url);
- builder.setBodyEncoding(DEFAULT_CHARSET);
- builder.setBody(s);
- Future<Response> f = builder.execute();
- String body = null;
- try {
- body = f.get().getResponseBody(DEFAULT_CHARSET);
- } catch (Exception e) {
- e.printStackTrace();
- }
- http.close();
- return body;
- }
- }
三、測試
相同結果下,對同一網絡請求平均測試20次請求性能
對於少量的網絡請求來說httpclient和異步的async-http-client相差無幾,甚至比異步還要快,但是在大量網絡請求來說異步性能可能更高,但是上面需要優化如減少鏈接創建、設置超時時間、設置重試次數等等。