HttpClient:
場景需求如下:
1、項目中需要與一個基於HTTP協議的第三方的接口進行對接
2、項目中需要動態的調用WebService服務(不生成本地源碼)
3、項目中需要利用其它網站的相關數據
這些需求可能或多或少的會發生在平時的開發中,針對每種情況,可能解決方案不止一種。本文使用HttpClient這種工具來講解HttpClient的相關知識,以及如何使用HttpClient完成上述需求。
HttpClient 不是瀏覽器?
有人說,HttpClient不就是一個瀏覽器嘛。。。
可能不少人對HttpClient會產生這種誤解,他們的觀點是這樣的:既然HttpClient是一個HTTP客戶端編程工具,那不就相當於是一個瀏覽器了嗎?無非它不能把HTML渲染出頁面而已罷了。
其實HttpClient不是瀏覽器,它是一個HTTP通信庫,因此它只提供一個通用瀏覽器應用程序所期望的功能子集,最根本的區別是HttpClient中沒有用戶界面,瀏覽器需要一個渲染引擎來顯示頁面,並解釋用戶輸入
HttpClient 是什么?
HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程序需要直接通過 HTTP 協議來訪問網絡資源。
雖然在 JDK 的 java.net 包中已經提供了訪問 HTTP 協議的基本功能,但是對於大部分應用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。
HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,並且它支持 HTTP 協議最新的版本和建議。
為什么要用HttpClient,它跟同類產品有什么區別呢?
1):提到HttpClient,就不得不提jdk原生的URL了。
jdk中自帶了基本的網絡編程,也就是java.net包下的一系列API。通過這些API,也可以完成網絡編程和訪問。
此外,另一個開源項目jsoup,它是一個簡單的HTML解析器,可以直接解析指定URL請求地址的內容,它可以通過DOM方式來取數據,也是比較方便的API。
那既然已經有這些工具了,為什么還是有好多好多使用HttpClient的呢?
這里其實是有一個錯誤的認識:Jsoup是解析器不假,但它跟HttpClient不是同類產品(類似Hibernate和MyBatis),實際上日常使用通常會用HttpClient配合Jsoup做網頁爬蟲。
HttpClient還是有很多好的特點(摘自Apache HttpClient官網):
1、基於標准、純凈的java語言。實現了HTTP1.0和HTTP1.1;
2、以可擴展的面向對象的結構實現了HTTP全部的方法(GET, POST等7種方法);
3、支持HTTPS協議;
4、通過HTTP代理建立透明的連接;
5、利用CONNECT方法通過HTTP代理建立隧道的HTTPS連接;
6、Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos認證方案;
7、插件式的自定義認證方案;
8、便攜可靠的套接字工廠使它更容易的使用第三方解決方案;
9、連接管理器支持多線程應用;支持設置最大連接數,同時支持設置每個主機的最大連接數,發現並關閉過期的連接;
10、自動處理Set-Cookie中的Cookie;
11、插件式的自定義Cookie策略;
12、Request的輸出流可以避免流中內容直接緩沖到socket服務器;
13、Response的輸入流可以有效的從socket服務器直接讀取相應內容;
14、在HTTP1.0和HTTP1.1中利用KeepAlive保持持久連接;
15、直接獲取服務器發送的response code和 headers;
16、設置連接超時的能力;
17、實驗性的支持HTTP1.1 response caching;
18、源代碼基於Apache License 可免費獲取。
HttpClient 能干嘛?
在后端開發過程中,后端服務不一定部署在一台服務器上,所以我們需要一種技術可以實現后端調用其他后端的服務,這種調用被稱為RPC(遠程過程調用),如下圖所示:
HttpClient編寫程序流程總結:
POM:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
流程:
1、創建HttpClient對象
這兒使用的是org.apache.http.impl.client.CloseableHttpClient,他是HttpClient接口的一個實例,創建該對象的最簡單方法:CloseableHttpClient client = HttpClients.createDefault();
HttpClients是創建CloseableHttpClient的工廠,采用默認的配置來創建實例,一般情況下我們就用這個默認的實例就足夠,后面我們可以去看下怎么定制自己需求配置的來創建HttpClient接口的實例。如果你去看這個函數的源代碼,你可以看到
org.apache.http.client.CookieStore,org.apache.http.client.config.RequestConfig等等都是采用默認的。
2、創建某種請求方法的實例
創建某種請求的實例,並指定請求的url,如果是get請求,創建對象HttpGet,如果是post 請求,創建對象HttpPost。
類型的還有 HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, 還有 HttpOptions。分別對應HEAD、POST PUT、DELETE、TRACE、OPTIONS方法,每個方法是做什么的如下表:
可以看得到在Http協議中,只有post方法和put方法的請求里面有實體
3、如果有請求參數的話,Get方法直接寫在url后面,例如
或者使用setParameter來設置參數:
使用 URIBuilder 對路徑請求信息進行封裝。
http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
POST 請求也可以使用 此方式進行攜帶參數。(攜帶參數有多種)
在介紹另外幾種:
3):發送請求
調用CloseableHttpClient對象的execute(HttpUriRequest request)發送請求,該方法返回一個CloseableHttpResponse對象。
CloseableHttpResponse response = client.execute(httpPost);
很明顯CloseableHttpResponse就是用了處理返回數據的實體,通過它我們可以拿到返回的狀態碼、首部、實體等等我們需要的東西。
4):獲取請求結果
調用CloseableHttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;
調用CloseableHttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容
通過CloseableHttpEntity的getEntity取得實體之后,有兩種處理結果的方法,
方法一:使用EntityUtils來處理。
該類是官方提供的一個處理實體的工具類,toSting方法將返回的實體轉換為字符串,
但是官網不建議使用這個,除非響應實體從一個可信HTTP服務器發起和已知是有限長度的。
方法二:使用InputStream來讀取
因為httpEntity.getContent方法返回的就是InputStream類型。
這種方法是官網推薦的方式,需要記得的是要自己釋放底層資源。
關閉連接釋放資源:
Demo 源碼下載: