JAVA實現HTTP請求 之 HTTPClient詳解
技術標籤:Javahttpclienthttpjava實現httpjava
目錄
八、寫的比較好的, 關於HttpClient 的 blogs:
一、目前JAVA實現HTTP請求的方法用的最多的有兩種:
- 通過HTTPClient這種第三方開源框架去實現。HTTPClient對HTTP的封裝性比較不錯,基本上能夠滿足我們大部分的需求,最新的HttpClient4.5是org.apache.http.impl.client下操作遠端 url的工具包;HttpClient3.1 是 org.apache.commons.httpclient下操作遠端 url的工具包,雖然已不再更新,但實現工作中使用httpClient3.1的程式碼還是有不少的.
- 另一種則是通過HttpURLConnection去實現,HttpURLConnection是JAVA的標準類,是JAVA比較原生的一種實現方式。不要用這個了,有現成的工具為什麼不用呢.
本篇介紹HTTPClient的使用.
二、依賴
使用httpclient之前,先引入maven依賴:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.9</version>
</dependency>
三、HttpClient 之 URIBuilder
建構函式
- URIBuilder()
- URIBuilder(final String string) 內部會建立URI物件: digestURI(new URI(string))
- URIBuilder(final URI uri)
非空的兩個構造實際內部都呼叫了digestURI(uri) 將URI物件解析並賦值給類的屬性.
URIBuilder類中方法:
① get相關方法
String url = "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=";
URIBuilder uriBuilder = new URIBuilder(url);
System.out.println(uriBuilder.getScheme());
System.out.println(uriBuilder.getUserInfo());
System.out.println(uriBuilder.getHost());
System.out.println(uriBuilder.getPort());
System.out.println(uriBuilder.getPath());
System.out.println(uriBuilder.getQueryParams());
System.out.println(uriBuilder.getFragment());
System.out.println(uriBuilder.getCharset());
輸出如下所示:
scheme:http
userinfo:null
host:www.google.com
port:-1 埠預設是80,當顯示指定埠時,此處便能取到值
path:/search
queryParams:[hl=en, q=httpclient, btnG=Google Search, aq=f, oq=]
fragment:null
charset:null
某些屬性含義未知手動設定一次
String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setFragment("111");
uriBuilder.setUserInfo("222", "333");
uriBuilder.setCharset(new GBK());
System.out.println(uriBuilder.build());
System.out.println(uriBuilder.getScheme());
System.out.println(uriBuilder.getUserInfo());
System.out.println(uriBuilder.getHost());
System.out.println(uriBuilder.getPath());
System.out.println(uriBuilder.getQueryParams());
System.out.println(uriBuilder.getFragment());
System.out.println(uriBuilder.getCharset());
輸出如下:
http://222:[email protected]/football/info/fb_match_hhad.php?m=102909#111
scheme:http
userInfo:222:333 沒見過這東西-。-
host:info.sporttery.cn
path:/football/info/fb_match_hhad.php
queryParams:[m=102909]
fragment:111 路由
charset:GBK
② 新增URI query引數方法
常用方法
- setParameters(final List nvps)
- setParameters(final NameValuePair… nvps)
- addParameters(final List nvps)
上面的方法我覺得倆set其實是一樣的, set會覆蓋原來的同名引數而add不會
這裡的NameValuePair :
只有一個實現類BasicNameValuePair就是用來設定引數鍵值對BasicNameValuePair(final String name, final String value)
String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
ArrayList<NameValuePair> objects = new ArrayList<>();
NameValuePair m = new BasicNameValuePair("m", "1");
objects.add(m);
ArrayList<NameValuePair> objects1 = new ArrayList<>();
NameValuePair m1 = new BasicNameValuePair("m", "8");
objects1.add(m1);
uriBuilder.setParameters(objects);
uriBuilder.addParameters(objects1);
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app?m=1&m=8
得出結論:set會覆蓋原來的同名引數而add不會
- addParameter(final String param, final String value)
- setParameter(final String param, final String value)
param和value會在這倆個方法內部組裝成BasicNameValuePair.
String url = "hhttp://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setParameter("m", "2");
uriBuilder.addParameter("m" ,"5");
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app?m=2&m=5
得出結論:set會覆蓋原來的同名引數而add不會
③Clears URI query parameters.
- clearParameters() 清除所有引數 (即?後的鍵值對)
String url = "http://ads-mediation.internal.zkq.sg/media/app?m=102909";
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.clearParameters();
System.out.println(uriBuilder.build());
輸出:http://ads-mediation.internal.zkq.sg/media/app
四、HttpClient之基本使用步驟:
使用HttpClient傳送請求、接收響應很簡單,一般需要如下幾步即可。
1. 建立HttpClient物件。
2. 建立請求方法的例項,並指定請求URL。如果需要傳送GET請求,建立HttpGet物件;如果需要傳送POST請求,建立HttpPost物件。
3. 如果需要傳送請求引數,可呼叫HttpGet、HttpPost共同的setParams(HetpParams params)方法來新增請求引數;對於HttpPost物件而言,也可呼叫setEntity(HttpEntity entity)方法來設定請求引數。
4. 呼叫HttpClient物件的execute(HttpUriRequest request)傳送請求,該方法返回一個HttpResponse。
5. 呼叫HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取伺服器的響應頭;呼叫HttpResponse的getEntity()方法可獲取HttpEntity物件,該物件包裝了伺服器的響應內容。程式可通過該物件獲取伺服器的響應內容。
6. 釋放連線。無論執行方法是否成功,都必須釋放連線
五、HttpClient之基本get用法
public class HttpClientDemo {
public void getRequest(String url) throws URISyntaxException, IOException {
//建立httpClient例項
CloseableHttpClient client = HttpClients.createDefault();
//建立一個uri物件
URIBuilder uriBuilder = new URIBuilder(url);
//塞入form引數
uriBuilder.addParameter("account", "123");
uriBuilder.addParameter("password", "123");
//建立httpGet遠端連線例項,這裡傳入目標的網路地址
HttpGet httpGet = new HttpGet(uriBuilder.build());
// 設定請求頭資訊,鑑權(沒有可忽略)
httpGet.setHeader("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
// 設定配置請求引數(沒有可忽略)
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 連線主機服務超時時間
.setConnectionRequestTimeout(35000)// 請求超時時間
.setSocketTimeout(60000)// 資料讀取超時時間
.build();
// 為httpGet例項設定配置
httpGet.setConfig(requestConfig);
//執行請求
CloseableHttpResponse response = client.execute(httpGet);
//獲取Response狀態碼
int statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
//獲取響應實體, 響應內容
HttpEntity entity = response.getEntity();
//通過EntityUtils中的toString方法將結果轉換為字串
String str = EntityUtils.toString(entity);
System.out.println(str);
response.close();
client.close();
}
}
(如果用try catch 記得關閉資源)
六、HttpClient之post - json用法
public String postRequest(String url, Map<String, Object> paramMap) {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 建立httpPost遠端連線例項
HttpPost post = new HttpPost(url);
String result = "";
try (CloseableHttpClient closeableHttpClient = httpClientBuilder.build()) {
// HttpEntity entity = new StringEntity(jsonDataStr);
// 修復 POST json 導致中文亂碼
HttpEntity entity = new StringEntity(paramMap.toString(), "UTF-8");
post.setEntity(entity);
post.setHeader("Content-type", "application/json");
HttpResponse resp = closeableHttpClient.execute(post);
try {
InputStream respIs = resp.getEntity().getContent();
byte[] respBytes = IOUtils.toByteArray(respIs);
result = new String(respBytes, Charset.forName("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
return result;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
七、HttpClient之post - form用法
form的關鍵在於生成NameValuePair ,這個集合裡面放入form 表單的元素.
隨後使用 HttpPost 的 setEntity(new UrlEncodedFormEntity(nameValuePair, HTTP.UTF_8)) 方法塞入生成的form元素集合.
總得來說, 就是通過一個NameValuePair集合來存放待提交的引數,並將這個引數集合傳入到一個UrlEncodedFormEntity中,然後呼叫HttpPost的setEntity()方法將構建好的UrlEncodedFormEntity傳入. 程式碼如下:
List<NameValuePair>params=newArrayList<NameValuePair>();
Params.add(new BasicNameValuePair(“username”,”admin”));
Params.add(new BasicNameValuePair(“password”,”123456”));
UrlEncodedFormEntity entity=newUrlEncodedFormEntity(params,”utf-8”);
httpPost.setEntity(entity);
示例程式碼如下 :
public static String postformRequest(String url, Map<String, Object> paramMap) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse httpResponse = null;
String result = "";
// 建立httpClient例項
httpClient = HttpClients.createDefault();
// 建立httpPost遠端連線例項
HttpPost httpPost = new HttpPost(url);
// 配置請求引數例項(不需要可忽略)
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(35000)// 設定連線主機服務超時時間
.setConnectionRequestTimeout(35000)// 設定連線請求超時時間
.setSocketTimeout(60000)// 設定讀取資料連線超時時間
.build();
// 為httpPost例項設定配置(不需要可忽略)
httpPost.setConfig(requestConfig);
// 設定請求頭
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
// 封裝表單引數
if (null != paramMap && paramMap.size() > 0) {
// 以下程式碼使用實現類BasicNameValuePair生成NameValuePair
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
// 通過map整合entrySet方法獲取entity
Set<Entry<String, Object>> entrySet = paramMap.entrySet();
// 迴圈遍歷,獲取迭代器
Iterator<Entry<String, Object>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Entry<String, Object> mapEntry = iterator.next();
nvps.add(new BasicNameValuePair(mapEntry.getKey(), mapEntry.getValue().toString()));
}
// 為httpPost設定封裝好的請求引數
try {
// post例項塞引數的方法
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
try {
// 伺服器返回的所有資訊都在HttpResponse中, httpClient物件執行post請求,並返回響應引數物件
httpResponse = httpClient.execute(httpPost);
// 先取出伺服器返回的狀態碼,如果等於200說明success
int code =httpResponse.getStatusLine().getStatusCode();
// 從響應物件中獲取響應內容
// EntityUtils.toString()有過載方法
// 這個靜態方法將HttpEntity轉換成字串,防止伺服器返回的資料帶有中文,所以在轉換的時候將字符集指定成utf-8即可
HttpEntity entity = httpResponse.getEntity();
result = EntityUtils.toString(entity,"UTF-8");
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 關閉資源
if (null != httpResponse) {
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != httpClient) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
八、寫的比較好的, 關於HttpClient 的 blogs:
放2個連結在這 :
https://www.cnblogs.com/mufengforward/p/10510337.html https://www.cnblogs.com/xiayahui/p/5623947.html