轉自:https://www.jianshu.com/p/375be5929bed
一、HttpClient使用詳解與實戰一:普通的GET和POST請求
簡介
HttpClient是Apache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包,並且它支持HTTP協議最新的版本和建議。
HttpClient最新版本是HttpClient 4.5.3 (GA)。
官方下載:http://hc.apache.org/downloads.cgi
主要特性
- 基於標准、純凈的Java語言,實現了HTTP1.0和HTTP1.1。
- 以可擴展的面向對象的結構實現了HTTP全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
- 支持加密的HTTPS協議(HTTP通過SSL協議)。
- 通過HTTP代理方式建立透明的連接。
- 利用CONNECT方法通過HTTP代理建立隧道的HTTPS連接。
- Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos認證方案。
- 插件式的自定義認證方案。
- 可插拔的安全套接字工廠,使得接入第三方解決方案變得更容易
- 連接管理支持使用多線程的的應用。支持設置最大連接數,同時支持設置每個主機的最大連接數,發現並關閉過期的連接。
- 自動化處理Set-Cookie:來自服務器的頭,並在適當的時候將它們發送回cookie。
- 可以自定義Cookie策略的插件化機制。
- Request的輸出流可以避免流中內容體直接從socket緩沖到服務器。
- Response的輸入流可以有效的從socket服務器直接讀取相應內容。
- 在HTTP1.0和HTTP1.1中使用用KeepAlive來保持持久連接。
- 可以直接獲取服務器發送的響應碼和響應頭部。
- 具備設置連接超時的能力。
- 支持HTTP/1.1 響應緩存。
- 源代碼基於Apache License 可免費獲取。
一般使用步驟
使用HttpClient發送請求、接收響應,一般需要以下步驟。
HttpGet請求響應的一般步驟:
1). 創建HttpClient
對象,可以使用HttpClients.createDefault()
;
2). 如果是無參數的GET請求,則直接使用構造方法HttpGet(String url)
創建HttpGet
對象即可;
如果是帶參數GET請求,則可以先使用URIBuilder(String url)
創建對象,再調用addParameter(String param, String value)
,或setParameter(String param, String value)
來設置請求參數,並調用build()方法構建一個URI對象。只有構造方法HttpGet(URI uri)
來創建HttpGet對象。
3). 創建HttpResponse
,調用HttpClient
對象的execute(HttpUriRequest request)
發送請求,該方法返回一個HttpResponse
。調用HttpResponse
的getAllHeaders()、getHeaders(String name)
等方法可獲取服務器的響應頭;調用HttpResponse
的getEntity()
方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。通過調用getStatusLine().getStatusCode()
可以獲取響應狀態碼。
4). 釋放連接。
HttpPost請求響應的一般步驟:
1). 創建HttpClient
對象,可以使用HttpClients.createDefault()
;
2). 如果是無參數的GET請求,則直接使用構造方法HttpPost(String url)
創建HttpPost
對象即可;
如果是帶參數POST請求,先構建HttpEntity對象並設置請求參數,然后調用setEntity(HttpEntity entity)創建HttpPost對象。
3). 創建HttpResponse
,調用HttpClient
對象的execute(HttpUriRequest request)
發送請求,該方法返回一個HttpResponse
。調用HttpResponse
的getAllHeaders()、getHeaders(String name)
等方法可獲取服務器的響應頭;調用HttpResponse
的getEntity()
方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。通過調用getStatusLine().getStatusCode()
可以獲取響應狀態碼。
4). 釋放連接。
實例代碼實戰
構建一個Maven項目,引入如下依賴
1 <dependency> 2 <groupId>org.apache.httpcomponents</groupId> 3 <artifactId>httpclient</artifactId> 4 <version>4.3.5</version> 5 </dependency> 6 <dependency> 7 <groupId>org.slf4j</groupId> 8 <artifactId>slf4j-log4j12</artifactId> 9 <version>1.7.7</version> 10 </dependency> 11 <dependency> 12 <groupId>org.apache.commons</groupId> 13 <artifactId>commons-io</artifactId> 14 <version>1.3.2</version> 15 </dependency>
實例1:普通的無參數GET請求
打開一個url,抓取響應結果輸出成html文件
1 /** 2 *普通的GET請求 3 */ 4 public class DoGET { 5 public static void main(String[] args) throws Exception { 6 // 創建Httpclient對象 7 CloseableHttpClient httpclient = HttpClients.createDefault(); 8 // 創建http GET請求 9 HttpGet httpGet = new HttpGet("http://www.baidu.com"); 10 CloseableHttpResponse response = null; 11 try { 12 // 執行請求 13 response = httpclient.execute(httpGet); 14 // 判斷返回狀態是否為200 15 if (response.getStatusLine().getStatusCode() == 200) { 16 //請求體內容 17 String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 18 //內容寫入文件 19 FileUtils.writeStringToFile(new File("E:\\devtest\\baidu.html"), content, "UTF-8"); 20 System.out.println("內容長度:"+content.length()); 21 } 22 } finally { 23 if (response != null) { 24 response.close(); 25 } 26 //相當於關閉瀏覽器 27 httpclient.close(); 28 } 29 } 30 }
實例2:執行帶參數的GET請求
模擬使用百度搜索關鍵字"java",並保存搜索結果為html文件
1 import java.io.File; 2 import java.net.URI; 3 import org.apache.commons.io.FileUtils; 4 import org.apache.http.client.methods.CloseableHttpResponse; 5 import org.apache.http.client.methods.HttpGet; 6 import org.apache.http.client.utils.URIBuilder; 7 import org.apache.http.impl.client.CloseableHttpClient; 8 import org.apache.http.impl.client.HttpClients; 9 import org.apache.http.util.EntityUtils; 10 /** 11 * 帶參數的GET請求 12 * 兩種方式: 13 * 1.直接將參數拼接到url后面 如:?wd=java 14 * 2.使用URI的方法設置參數 setParameter("wd", "java") 15 */ 16 public class DoGETParam { 17 public static void main(String[] args) throws Exception { 18 // 創建Httpclient對象 19 CloseableHttpClient httpclient = HttpClients.createDefault(); 20 // 定義請求的參數 21 URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "java").build(); 22 // 創建http GET請求 23 HttpGet httpGet = new HttpGet(uri); 24 //response 對象 25 CloseableHttpResponse response = null; 26 try { 27 // 執行http get請求 28 response = httpclient.execute(httpGet); 29 // 判斷返回狀態是否為200 30 if (response.getStatusLine().getStatusCode() == 200) { 31 String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 32 //內容寫入文件 33 FileUtils.writeStringToFile(new File("E:\\devtest\\baidu-param.html"), content, "UTF-8"); 34 System.out.println("內容長度:"+content.length()); 35 } 36 } finally { 37 if (response != null) { 38 response.close(); 39 } 40 httpclient.close(); 41 } 42 } 43 }
實例3:執行普通的POST請求
無參數的POST請求,並設置Header來偽裝瀏覽器請求
1 import org.apache.commons.io.FileUtils; 2 import org.apache.http.client.methods.CloseableHttpResponse; 3 import org.apache.http.client.methods.HttpPost; 4 import org.apache.http.impl.client.CloseableHttpClient; 5 import org.apache.http.impl.client.HttpClients; 6 import org.apache.http.util.EntityUtils; 7 8 import java.io.File; 9 10 /** 11 * 常規post請求 12 * 可以設置Header來偽裝瀏覽器請求 13 */ 14 public class DoPOST { 15 public static void main(String[] args) throws Exception { 16 // 創建Httpclient對象 17 CloseableHttpClient httpclient = HttpClients.createDefault(); 18 // 創建http POST請求 19 HttpPost httpPost = new HttpPost("http://www.oschina.net/"); 20 //偽裝瀏覽器請求 21 httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"); 22 CloseableHttpResponse response = null; 23 try { 24 // 執行請求 25 response = httpclient.execute(httpPost); 26 // 判斷返回狀態是否為200 27 if (response.getStatusLine().getStatusCode() == 200) { 28 String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 29 //內容寫入文件 30 FileUtils.writeStringToFile(new File("E:\\devtest\\oschina.html"), content, "UTF-8"); 31 System.out.println("內容長度:"+content.length()); 32 } 33 } finally { 34 if (response != null) { 35 response.close(); 36 } 37 httpclient.close(); 38 } 39 } 40 }
實例4:執行帶參數的POST請求
模擬開源中國檢索java,並偽裝瀏覽器請求,輸出響應結果為html文件

1 import java.io.File; 2 import java.util.ArrayList; 3 import java.util.List; 4 5 import org.apache.commons.io.FileUtils; 6 import org.apache.http.NameValuePair; 7 import org.apache.http.client.entity.UrlEncodedFormEntity; 8 import org.apache.http.client.methods.CloseableHttpResponse; 9 import org.apache.http.client.methods.HttpPost; 10 import org.apache.http.impl.client.CloseableHttpClient; 11 import org.apache.http.impl.client.HttpClients; 12 import org.apache.http.message.BasicNameValuePair; 13 import org.apache.http.util.EntityUtils; 14 15 /** 16 * 帶有參數的Post請求 17 * NameValuePair 18 */ 19 public class DoPOSTParam { 20 public static void main(String[] args) throws Exception { 21 // 創建Httpclient對象 22 CloseableHttpClient httpclient = HttpClients.createDefault(); 23 // 創建http POST請求 24 HttpPost httpPost = new HttpPost("http://www.oschina.net/search"); 25 // 設置2個post參數,一個是scope、一個是q 26 List<NameValuePair> parameters = new ArrayList<NameValuePair>(0); 27 parameters.add(new BasicNameValuePair("scope", "project")); 28 parameters.add(new BasicNameValuePair("q", "java")); 29 // 構造一個form表單式的實體 30 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters); 31 // 將請求實體設置到httpPost對象中 32 httpPost.setEntity(formEntity); 33 //偽裝瀏覽器 34 httpPost.setHeader("User-Agent", 35 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"); 36 CloseableHttpResponse response = null; 37 try { 38 // 執行請求 39 response = httpclient.execute(httpPost); 40 // 判斷返回狀態是否為200 41 if (response.getStatusLine().getStatusCode() == 200) { 42 String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 43 //內容寫入文件 44 FileUtils.writeStringToFile(new File("E:\\devtest\\oschina-param.html"), content, "UTF-8"); 45 System.out.println("內容長度:"+content.length()); 46 } 47 } finally { 48 if (response != null) { 49 response.close(); 50 } 51 httpclient.close(); 52 } 53 } 54 }
總結
本文介紹了HttpClient的特性,是按照官方英文文檔翻譯而來,然后分別介紹了HttpGet和HttpPost的一般使用步驟,最后給出了4個簡單的實例的Java代碼。下一章節我們會介紹HttpClient連接池管理以及Spring整合HttpClient的具體過程。
二、HttpClient 學習記錄---URIBuilder
https://blog.csdn.net/wxy1234556/article/details/79022402
構造函數
URIBuilder()
URIBuilder(final String string) 內部會創建URI對象
URIBuilder(final URI uri)
非空的兩個構造實際內部都調用了digestURI(uri) 將URI對象解析並賦值給類的屬性
類屬性
1 String url = "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq="; 2 URIBuilder uriBuilder = new URIBuilder(url); 3 System.out.println(uriBuilder.getScheme()); 4 System.out.println(uriBuilder.getUserInfo()); 5 System.out.println(uriBuilder.getHost()); 6 System.out.println(uriBuilder.getPort()); 7 System.out.println(uriBuilder.getPath()); 8 System.out.println(uriBuilder.getQueryParams()); 9 System.out.println(uriBuilder.getFragment()); 10 System.out.println(uriBuilder.getCharset());
輸出如下所示:
scheme:http
userinfo:null
host:www.google.com
prot:-1 端口默認是80,當顯示指定端口時,此處便能取到值
path:/search
queryParams:[hl=en, q=httpclient, btnG=Google Search, aq=f, oq=]
fragment:null
charset:null
某些屬性含義未知手動設置一次
1 String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909"; 2 URIBuilder uriBuilder = new URIBuilder(url); 3 uriBuilder.setFragment("111"); 4 uriBuilder.setUserInfo("222", "333"); 5 uriBuilder.setCharset(new GBK()); 6 System.out.println(uriBuilder.build()); 7 System.out.println(uriBuilder.getScheme()); 8 System.out.println(uriBuilder.getUserInfo()); 9 System.out.println(uriBuilder.getHost()); 10 System.out.println(uriBuilder.getPath()); 11 System.out.println(uriBuilder.getQueryParams()); 12 System.out.println(uriBuilder.getFragment()); 13 System.out.println(uriBuilder.getCharset());
輸出如下:
http://222:333@info.sporttery.cn/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
常用方法
URIBuilder setParameters(final List nvps)
URIBuilder addParameters(final List nvps)
URIBuilder setParameters(final NameValuePair… nvps)
上面這三個方法中我覺得倆set其實是一樣的
1 String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909"; 2 URIBuilder uriBuilder = new URIBuilder(url); 3 ArrayList<NameValuePair> objects = new ArrayList<>(); 4 ArrayList<NameValuePair> objects1 = new ArrayList<>(); 5 NameValuePair m = new BasicNameValuePair("m", "1"); 6 objects.add(m); 7 NameValuePair m1 = new BasicNameValuePair("m", "8"); 8 objects1.add(m1); 9 uriBuilder.setParameters(objects); 10 uriBuilder.addParameters(objects1); 11 System.out.println(uriBuilder.build());
輸出:http://info.sporttery.cn/football/info/fb_match_hhad.php?m=1&m=8
得出結論:set會覆蓋原來的同名參數而add不會
1 URIBuilder addParameter(final String param, final String value) 2 URIBuilder setParameter(final String param, final String value) 3 4 String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909"; 5 URIBuilder uriBuilder = new URIBuilder(url); 6 uriBuilder.setParameter("m", "2"); 7 uriBuilder.addParameter("m" ,"5"); 8 System.out.println(uriBuilder.build());
輸出:http://info.sporttery.cn/football/info/fb_match_hhad.php?m=2&m=5
得出結論:set會覆蓋原來的同名參數而add不會
1 URIBuilder clearParameters() 2 3 String url = "http://info.sporttery.cn/football/info/fb_match_hhad.php?m=102909"; 4 URIBuilder uriBuilder = new URIBuilder(url); 5 uriBuilder.clearParameters(); 6 System.out.println(uriBuilder.build());
輸出:http://info.sporttery.cn/football/info/fb_match_hhad.php
就是清除所有參數
NameValuePair
只有一個實現類BasicNameValuePair就是用來設置參數鍵值對BasicNameValuePair(final String name, final String value)
NameValuePair的用法
定義了一個list,該list的數據類型是NameValuePair(簡單名稱值對節點類型),這個代碼多處用於Java像url發送Post請求。在發送post請求時用該list來存放參數。
發送請求的大致過程如下:
String url="http://www.baidu.com";
HttpPost httppost=new HttpPost(url); //建立HttpPost對象
List<NameValuePair> params=new ArrayList<NameValuePair>();
//建立一個NameValuePair數組,用於存儲欲傳送的參數
params.add(new BasicNameValuePair("pwd","2544"));
//添加參數
httppost.setEntity(new UrlEncodedFormEntity(params,HTTP.UTF_8));
//設置編碼
HttpResponse response=new DefaultHttpClient().execute(httppost);
//發送Post,並返回一個HttpResponse對象
https://www.cnblogs.com/hunt/p/7071053.html