天天看點

HttpClient4.5教程-基礎 1.1

1.1 Request 的執行

HttpClient最必不可少的功能就是執行HTTP的方法,執行HTTP方法會涉及到一個或者多個HTTP request/HTTP response交換,而這些過程通常會在HttpClient内部完成。使用者送出一個request的對象去執行,HttpClient會發送這個request到目标伺服器并且獲得一個對應的response對象,如果不成功的話則抛出一個異常。

自然而然,滿足了上面描述的HttpClient接口就是HttpClient API的主要入口。

下面是一個最簡單的request執行過程:

1.1.1 HTTP request

所有的HTTP request都有一個請求線,包含了請求的方法名稱,請求的URI和HTTP協定版本。

HttpClient開箱即用的支援所有HTTP/1.1中定義的HTTP方法,包括GET,HEAD,POST,PUT,DELETE,TRACE 和 OPTIONS,這些HTTP方法類型都有一個與之對應的類:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace 和 HttpOptions。

Request-URI是一個統一資源定位符,它指明了用于處理該request的資源的位置。HTTP request URIs包含了一個協定類型,主機名,可選端口,資源路徑,可選查詢參數,可選片段。

輸出:

1.1.2 HTTP response

HTTP response是伺服器在接收并且處理完request消息之後傳回給用戶端的消息,消息的第一行包含了協定版本,status code和與之關聯的文本。

1.1.3 消息頭處理

HTTP消息包含多個header,這些header描述了消息的屬性比如content length,content type等等,HttpClient提供了取出,添加,删除和周遊header的方法。

擷取所有指定headers的最高效的方式是使用HeaderIterator接口。

該接口同時也提供HTTP消息轉換到獨立header元素的便利方法。

1.1.4 HTTP entity

HTTP消息可以攜帶跟request和response相關聯的content entity。由于這些Entity是可選的,是以他們在某些request和response中可以查找到,有些則查不到。使用了entity的request被稱為entity封裝請求,HTTP定義了兩種entity封裝請求方法:POST 和 PUT。Response通常會封裝一個content entity。不同的方法會有對應的異常,比如對于HEAD來說就有204 No Content,304

Not Modified, 205 Reset Content異常。

HttpClient根據内容來源将Entities區分為3種,根據内容來源區分為:

streamed: 内容來自于流或者實時産生。特别的是,這個分類包含了從HTTP responses接收到的entities,Streamed entities通常不可重複。

self-contained: 内容來自于記憶體或者通過獨立于connection或者其他entity的手段獲得,self-contained entities通常可以重複,其也是封裝了entity的HTTP request最常用的Entities類型。

wrapping : 内容來自于其他的entity。

這種區分對于HTTP response輸出内容時的連接配接管理是非常重要的。對于request entites來說,由于其是被應用建立并且通過HttpClient發送,streamed和self-contained有什麼不同就沒有那麼重要。

由此,建議将不可重複的entites視為streamed,可以重複的entities視為self-contained。

1.1.4.1 可重複的entities

一個entity能夠重複,表明它的内容可以被讀取多次,這種情況隻會在self contained entities中發生(比如ByteArrayEntity 或者 StringEntity)

1.1.4.2 使用HTTP entities

Entity可以同時代表二進制和文字内容,支援對字元進行編碼,比如對character content進行編碼。

Entity産生于request(封裝内容 )執行時,或者request成功請求并且response body用于發送結果資料到用戶端時。

從Entity中讀取内容,可以通過HttpEntity#getContent()擷取input stream,也可以向HttpEntity#writeTo(OutputStream)提供一個output stream,該方法會将内容一次性全部寫回給指派的stream。

當消息到達并且Entity已經被接收時,可以用 HttpEntity#getContentType() 和 HttpEntity#getContentLength() 方法讀取常用的中繼資料,如Content-Type 和 Content-Length 頭資訊,Content-Type頭資訊包含文本的mime-type編碼資訊如 text/plain 或者 text/html,該資訊可以通過 HttpEntity#getContentType() 擷取到,如果Header裡面不包含這些資訊,那麼 HttpEntity#getContentLength()

 會傳回-1 并且  HttpEntity#getContentType()  傳回 NULL,如果Header包含這些資訊,那麼 HttpEntity#getContentType() 會傳回 Header 對象。

當建立一個出站消息的entity時,必須同時指定其相關的參數。

1.1.5 確定釋放低級資源

為了保證恰當的釋放系統資源,使用完畢後必須關閉entity相關的stream和response。

關閉内容流和關閉response的不同之處在于,關閉内容流會嘗試通過消費entity的content來保持底層連接配接,而關閉response則是直接關閉和丢棄掉這個連接配接。

注意 HttpEntity#writeTo(OutputStream)  方法也需要在entity被寫出到流之後恰當的釋放系統資源。如果通過HttpEntity#getContent()擷取了java.io.InputStream流的執行個體,那麼在finally階段也需要關閉該流。

當處理streaming entites時,可以使用 EntityUtils#consume(HttpEntity) 方法來確定entity内容已經被完全消費并且底層stream已經被關閉。

有另一種情況是,當我們隻需要從response content裡面擷取一小部分資料,但是消費剩餘資料和保持連接配接複用的性能損失又太高時,我們可以直接關閉response。

這樣這個連接配接不會被複用,連接配接的所有資源都會被正确的釋放掉。

1.1.6 消費entity内容

消費Entity内容的推薦方式是使用 HttpEntity#getContent() 或者 HttpEntity#writeTo(OuptputStream) 方法,也可以使用EntityUtils類,該類提供了一些靜态方法來簡化讀取Entity内容或者其他資訊。通過使用該類的某些方法,你可以以String /byte[] 方式來擷取整個content body,進而替代直接讀取 InputStream 的方式。但是,除非你知道response entity來自于可信HTTP

server 并且其長度有限,否則不推薦使用EntityUtils。

某些情況下你可能讀取entity content不止一次,這時就需要将内容通過記憶體或者磁盤的方式緩存起來,最簡單的實作方式就是使用BufferedHttpEntity包裝源Entity,該類會将源 Entity 的内容讀取到記憶體中。如果通過其他方式來實作,那麼就必須要儲存一個源entity了。

1.1.7 生産 entity content

HttpClient提供多個可以通過HTTP連接配接高效的輸出内容的類,這些類的執行個體可以跟POST和PUT等request相關聯并且為request封裝entity内容,HttpClient提供了最常用的資料容器如string, byte array , input stream 和檔案 : StringEntity , ByteArrayEntity,InputStreamEntity,和FileEntity。

注意 InputStreamEntity 不可以重複,因為它隻能從底層資料流讀取一次。通常建議用HttpEntity的實作(self-contained)來替代普通的InputStreamEntity,FileEntity是一個不錯的起始點。

1.1.7.1 HTML表單

許多應用程式需要模拟表單送出的過程,比如登入web應用或者送出input 資料,HttpClient提供了UrlEncodedFormEntity類來簡化這個過程。

UrlEncodedFormEntity執行個體會使用URL encoding來編碼參數并且産生出如下内容:

1.1.7.2 内容分塊

通常來說,建議讓HttpClient選擇最合适的傳輸編碼,HttpClient選擇的傳輸編碼會基于被傳輸的HTTP消息的屬性而定。你可以通過設定HttpEntity#setChunked()為true來通知HttpClient需要進行chunk編碼。注意HttpClient隻是把這一辨別當做一個提示使用,該值在不支援chunk編碼的HTTP協定版本中如HTTP/1.0中會被忽略。

1.1.8 Response handlers

最簡單和友善處理response的方式是使用ResponseHandler,該類包含了handleResponse(HttpResponse response)方法。該方法使得使用者完全不需要去操心連接配接管理的事情。當使用ResponseHandler時,HttpClient會自動確定将連接配接釋放回連接配接管理器,無論request是否執行成功。

上一篇: drbd配置參數
下一篇: word不能儲存