參考:https://jingyan.baidu.com/article/154b46317353d228ca8f4112.html
參考:https://www.jianshu.com/p/a44407f48321
(一) 自httpclient-4.4開始,官方對代碼進行了很多調整,4.4以前的很多class和method都過時了,而國內之前很多關於httpclient的分享都是4.4之前的。
個人感覺使用Httpclient比較重要的是看它的代碼,和官方的一些例子,可能是網絡知識比較短板的原因,官方的tutorial其實看起來挺不清晰的,感覺主線不明確,不能引導你很好的學習,建議初學的人同時結合官網、源碼、官方例子、tutorial進行學習。
HttpClient-4.5.jar
public void firstHttpClientDemo(){
try {
String url = "http://www.baidu.com";
// 使用默認配置創建httpclient的實例
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
// HttpGet get = new HttpGet(url);
CloseableHttpResponse response = client.execute(post);
// CloseableHttpResponse response = client.execute(get);
// 服務器返回碼
int status_code = response.getStatusLine().getStatusCode();
System.out.println("status_code = " + status_code);
// 服務器返回內容,請求到的是一個頁面
String respStr = null;
HttpEntity entity = response.getEntity();
if(entity != null) {
respStr = EntityUtils.toString(entity, "UTF-8");
}
System.out.println("respStr = " + respStr);
// 釋放資源
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
這個demo主要是完成基本的交互過程,發送請求,接收消息,如果只是做小程序或者不是特別大並發量的系統,基本已經夠用了。
進行一些說明:
1.需要向服務器發送請求,我們需要一個org.apache.http.client.HttpClient
的實例對象,一般使用的都是org.apache.http.impl.client.CloseableHttpClient
,創建該對象的最簡單方法是CloseableHttpClient client = HttpClients.createDefault();
,HttpClients是負責創建CloseableHttpClient的工廠,現在我們用最簡單的方法就是使用默認配置去創建實例,后面我們再討論有參數定制需求的實例創建方法。我們可以通過打斷點的方式看到這個默認的實例對象的連接管理器 : org.apache.http.conn.HttpClientConnectionManager
、請求配置 : org.apache.http.client.config.RequestConfig
等配置的默認參數,這些都是后面需要了解的。
HttpPost post = new HttpPost(url);
表示我們希望用那種交互方法與服務器交互,HttpClient為每種交互方法都提供了一個類:HttpGet,
HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, 還有 HttpOptions。
3.向服務器提交請求CloseableHttpResponse response = client.execute(post);
,很明顯`CloseableHttpResponse就是用了處理返回數據的實體,通過它我們可以拿到返回的狀態碼、返回實體等等我們需要的東西。
4.EntityUtils是官方提供一個處理返回實體的工具類,toString方法負責將返回實體裝換為字符串,官方是不太建議使用這個類的,除非返回數據的服務器絕對可信和返回的內容長度是有限的。官方建議是自己使用HttpEntity#getContent()或者HttpEntity#writeTo(OutputStream),需要提醒的是記得關閉底層資源。
5.EntityUtils.consume(entity);
負責釋放資源,通過源碼可知,是需要把底層的流關閉:
-
InputStream instream = entity.getContent();
-
if (instream != null) {
-
instream.close();
-
}
-
好了,到此已經完成了httpclient的第一個demo。
jar包地址:Apache HttpClient 4.5.2、Apache HttpCore 4.4
(二)跟服務器交互,更多的是發送數據,然后接收到服務器返回的數據,一般我們利用http-client中的實體(Entity),具體在org.apache.http.entity包下面的類來封裝我們的請求,從服務器上接收的也是實體,這個在上一篇的response.getEntity()
可知。
HttpClient根據內容的出處來區分3種實體:
-
流式(Stream):內容從流(Stream)中接收,或者在運行中產生(generated on the fly)。
-
自我包含(self-contained):內容在內存中或通過獨立的連接或其他實體中獲得。
-
包裝(wrapping):內容是從其他實體(Entity)中獲得的。
只有自我包含的實體是可以重復的,重復意味着可以被多次讀取,如多次調用EntityUtils.toString(entity)
。具體來講有如:StringEntity、ByteArrayEntity……
廢話不多說,上代碼,看看如何向服務器發送請求。
import org.apache.http.NameValuePair;
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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
@Test
public void requestParaDemo(){
try {
String url = "http://localhost:9090";
// 使用默認配置創建httpclient的實例
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
/**
* 設置參數,常用的有StringEntity,UrlEncodedFormEntity,MultipartEntity
* 具體看org.apache.http.entity包
*/
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("username", "張三"));
params.add(new BasicNameValuePair("password", "123456"));
UrlEncodedFormEntity e = new UrlEncodedFormEntity(params, "UTF-8");
post.setEntity(e);
CloseableHttpResponse response = client.execute(post);
// 服務器返回碼
int status_code = response.getStatusLine().getStatusCode();
System.out.println(status_code);
// 服務器返回內容
String respStr = null;
HttpEntity entity = response.getEntity();
if(entity != null) {
respStr = EntityUtils.toString(entity, "UTF-8");
}
System.out.println("respStr = " + respStr);
// 釋放資源
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
}
}
代碼模擬了客戶端向服務器發送一個表單數據,最常用的場景就是發送報文數據/登陸動作了。
這段代碼應該不需要過多的解釋。
來欣賞一下官方代碼是如何完成一個登陸動作的:
public void ClientFormLogin()throws Exception{BasicCookieStore cookieStore = new BasicCookieStore();
CloseableHttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
try {
HttpGet httpget = new HttpGet("https://someportal/");
CloseableHttpResponse response1 = httpclient.execute(httpget);
try {
HttpEntity entity = response1.getEntity();
System.out.println("Login form get: " + response1.getStatusLine());
EntityUtils.consume(entity);
System.out.println("Initial set of cookies:");
List<Cookie> cookies = cookieStore.getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
} finally {
response1.close();
}
HttpUriRequest login = RequestBuilder.post().setUri(new URI("https://someportal/"))
.addParameter("IDToken1", "username").addParameter("IDToken2", "password").build();
CloseableHttpResponse response2 = httpclient.execute(login);
try {
HttpEntity entity = response2.getEntity();
System.out.println("Login form get: " + response2.getStatusLine());
EntityUtils.consume(entity);
System.out.println("Post logon cookies:");
List<Cookie> cookies = cookieStore.getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i).toString());
}
}
} finally {
response2.close();
}
} finally {
httpclient.close();
}
}
(三)我們在使用HttpClient的時候更多的是需要自己根據業務特點創建自己定制化的HttpClient實例,而不是像上面那樣使用
-
// 使用默認配置創建httpclient的實例
-
CloseableHttpClient client = HttpClients.createDefault();
-
/**
-
* 使用httpclient-4.5.2發送請求,配置請求定制化參數
-
* @author chmod400
-
* 2016.3.28
-
*/
@Test
public void requestConfigDemo(){
try {
String url = "http://www.baidu.com";
/**
* 請求參數配置
* connectionRequestTimeout:
* 從連接池中獲取連接的超時時間,超過該時間未拿到可用連接,
* 會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
* connectTimeout:
* 連接上服務器(握手成功)的時間,超出該時間拋出connect timeout
* socketTimeout:
* 服務器返回數據(response)的時間,超過該時間拋出read timeout
*/
CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom()
.setConnectionRequestTimeout(2000).setConnectTimeout(2000).setSocketTimeout(2000).build()).build();
HttpPost post = new HttpPost(url);
// HttpGet get = new HttpGet(url);
CloseableHttpResponse response = client.execute(post);
// CloseableHttpResponse response = client.execute(get);
// 服務器返回碼
int status_code = response.getStatusLine().getStatusCode();
System.out.println("status_code = " + status_code);
// 服務器返回內容
String respStr = null;
HttpEntity entity = response.getEntity();
if(entity != null) {
respStr = EntityUtils.toString(entity, "UTF-8");
}
System.out.println("respStr = " + respStr);
// 釋放資源
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
}
需要說明的是,需要自己定制HttpClient客戶端的話,我們使用HttpClients.custom()
,然后調用各種set方法即可,一般建議使用HttpClients.custom().setDefaultRequestConfig()
,org.apache.http.client.config.RequestConfig
類提供了很多可定制的參數,我們可以根據自己的配置來使用相關配置。有幾個參數我們自己必須設置一下
-
connectionRequestTimeout:從連接池中獲取連接的超時時間,超過該時間未拿到可用連接,
會拋出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
-
connectTimeout:連接上服務器(握手成功)的時間,超出該時間拋出connect timeout
socketTimeout:服務器返回數據(response)的時間,超過該時間拋出read timeout
通過打斷點的方式我們知道,HttpClients在我們沒有指定連接工廠的時候默認使用的是連接池工廠org.apache.http.impl.conn.PoolingHttpClientConnectionManager.PoolingHttpClientConnectionManager(Registry<ConnectionSocketFactory>)
,所以我們需要配置一下從連接池獲取連接池的超時時間。
以上3個超時相關的參數如果未配置,默認為-1,意味着無限大,就是一直阻塞等待!
官方提供了一個demo,里面有一些最常用的配置代碼,僅供參考:
/*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.examples.client;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.CodingErrorAction;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.MessageConstraints;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpConnectionFactory;
import org.apache.http.conn.ManagedHttpClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParser;
import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;
import org.apache.http.io.HttpMessageParser;
import org.apache.http.io.HttpMessageParserFactory;
import org.apache.http.io.HttpMessageWriterFactory;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicLineParser;
import org.apache.http.message.LineParser;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;
/**
* This example demonstrates how to customize and configure the most common aspects
* of HTTP request execution and connection management.
*/
public class ClientConfiguration {
public final static void main(String[] args) throws Exception {
// Use custom message parser / writer to customize the way HTTP
// messages are parsed from and written out to the data stream.
HttpMessageParserFactory<HttpResponse> responseParserFactory = new DefaultHttpResponseParserFactory() {
@Override
public HttpMessageParser<HttpResponse> create(
SessionInputBuffer buffer, MessageConstraints constraints) {
LineParser lineParser = new BasicLineParser() {
@Override
public Header parseHeader(final CharArrayBuffer buffer) {
try {
return super.parseHeader(buffer);
} catch (ParseException ex) {
return new BasicHeader(buffer.toString(), null);
}
}
};
return new DefaultHttpResponseParser(
buffer, lineParser, DefaultHttpResponseFactory.INSTANCE, constraints) {
@Override
protected boolean reject(final CharArrayBuffer line, int count) {
// try to ignore all garbage preceding a status line infinitely
return false;
}
};
}
};
HttpMessageWriterFactory<HttpRequest> requestWriterFactory = new DefaultHttpRequestWriterFactory();
// Use a custom connection factory to customize the process of
// initialization of outgoing HTTP connections. Beside standard connection
// configuration parameters HTTP connection factory can define message
// parser / writer routines to be employed by individual connections.
HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory = new ManagedHttpClientConnectionFactory(
requestWriterFactory, responseParserFactory);
// Client HTTP connection objects when fully initialized can be bound to
// an arbitrary network socket. The process of network socket initialization,
// its connection to a remote address and binding to a local one is controlled
// by a connection socket factory.
// SSL context for secure connections can be created either based on
// system or application specific properties.
SSLContext sslcontext = SSLContexts.createSystemDefault();
// Create a registry of custom connection socket factories for supported
// protocol schemes.
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
// Use custom DNS resolver to override the system DNS resolution.
DnsResolver dnsResolver = new SystemDefaultDnsResolver() {
@Override
public InetAddress[] resolve(final String host) throws UnknownHostException {
if (host.equalsIgnoreCase("myhost")) {
return new InetAddress[] { InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) };
} else {
return super.resolve(host);
}
}
};
// Create a connection manager with custom configuration.
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
socketFactoryRegistry, connFactory, dnsResolver);
// Create socket configuration
SocketConfig socketConfig = SocketConfig.custom()
.setTcpNoDelay(true)
.build();
// Configure the connection manager to use socket configuration either
// by default or for a specific host.
connManager.setDefaultSocketConfig(socketConfig);
connManager.setSocketConfig(new HttpHost("somehost", 80), socketConfig);
// Validate connections after 1 sec of inactivity
connManager.setValidateAfterInactivity(1000);
// Create message constraints
MessageConstraints messageConstraints = MessageConstraints.custom()
.setMaxHeaderCount(200)
.setMaxLineLength(2000)
.build();
// Create connection configuration
ConnectionConfig connectionConfig = ConnectionConfig.custom()
.setMalformedInputAction(CodingErrorAction.IGNORE)
.setUnmappableInputAction(CodingErrorAction.IGNORE)
.setCharset(Consts.UTF_8)
.setMessageConstraints(messageConstraints)
.build();
// Configure the connection manager to use connection configuration either
// by default or for a specific host.
connManager.setDefaultConnectionConfig(connectionConfig);
connManager.setConnectionConfig(new HttpHost("somehost", 80), ConnectionConfig.DEFAULT);
// Configure total max or per route limits for persistent connections
// that can be kept in the pool or leased by the connection manager.
connManager.setMaxTotal(100);
connManager.setDefaultMaxPerRoute(10);
connManager.setMaxPerRoute(new HttpRoute(new HttpHost("somehost", 80)), 20);
// Use custom cookie store if necessary.
CookieStore cookieStore = new BasicCookieStore();
// Use custom credentials provider if necessary.
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
// Create global request configuration
RequestConfig defaultRequestConfig = RequestConfig.custom()
.setCookieSpec(CookieSpecs.DEFAULT)
.setExpectContinueEnabled(true)
.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
.build();
// Create an HttpClient with the given custom dependencies and configuration.
CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(connManager)
.setDefaultCookieStore(cookieStore)
.setDefaultCredentialsProvider(credentialsProvider)
.setProxy(new HttpHost("myproxy", 8080))
.setDefaultRequestConfig(defaultRequestConfig)
.build();
try {
HttpGet httpget = new HttpGet("http://httpbin.org/get");
// Request configuration can be overridden at the request level.
// They will take precedence over the one set at the client level.
RequestConfig requestConfig = RequestConfig.copy(defaultRequestConfig)
.setSocketTimeout(5000)
.setConnectTimeout(5000)
.setConnectionRequestTimeout(5000)
.setProxy(new HttpHost("myotherproxy", 8080))
.build();
httpget.setConfig(requestConfig);
// Execution context can be customized locally.
HttpClientContext context = HttpClientContext.create();
// Contextual attributes set the local context level will take
// precedence over those set at the client level.
context.setCookieStore(cookieStore);
context.setCredentialsProvider(credentialsProvider);
System.out.println("executing request " + httpget.getURI());
CloseableHttpResponse response = httpclient.execute(httpget, context);
try {
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
System.out.println(EntityUtils.toString(response.getEntity()));
System.out.println("----------------------------------------");
// Once the request has been executed the local context can
// be used to examine updated state and various objects affected
// by the request execution.
// Last executed request
context.getRequest();
// Execution route
context.getHttpRoute();
// Target auth state
context.getTargetAuthState();
// Proxy auth state
context.getTargetAuthState();
// Cookie origin
context.getCookieOrigin();
// Cookie spec used
context.getCookieSpec();
// User security token
context.getUserToken();
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
(四)
先簡單介紹連接工廠(
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();
Registry<ConnectionSocketFactory> r = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build();