很多其它HttpClient4.5中文教程請查看:點擊打開鏈接
1.1.4.HTTP實體(HTTP Entity)
HTTP報文可以攜帶與請求或對應相關聯的內容實體。實體存在於某些請求、響應中,它門是可選的。使用實體的請求被稱為內含實體請求【譯者:原文為entity enclosing requests。我把它翻譯為 內含實體請求】。
HTTP規范定義了兩種內含實體請求。POST和PUT。而響應總是內含實體。
但有些響應不符合這一規則,比方,對HEAD方法的響應和狀態為204 No Content, 304 Not Modified, 205 Reset Content的響應。
根據實體的內容來源,HttpClient區分出三種實體:
流式實體(streamed):內容來源於一個流。或者在執行中產生【譯者:原文為generated on the fly】。特別的,這個類別包含從響應中接收到的實體。
流式實體不可反復。
自包括實體(self-contained):在內存中的內容或者通過獨立的連接/其它實體獲得的內容。自包括實體是可反復的。這類實體大部分是HTTP內含實體請求。
包裝實體(wrapping):從另外一個實體中獲取內容。
1.1.4.1 可反復實體
一個實體可以被反復,意味着它的內容可以被讀取多次。它僅可能是自包括實體(像ByteArrayEntity或StringEntity)
1.1.4.2 使用HTTP實體
因為一個實體可以表現為二進制和字符內容,它支持二進制編碼(為了支持后者。即字符內容)。
實體將會在一些情況下被創建:當運行一個含有內容的請求時或者當請求成功。響應體作為結果返回給client時。為了讀取實體的內容。能夠通過HttpEntity#getContent() 方法取出輸入流。返回一個java.io.InputStream,或者提供一個輸出流給HttpEntity#writeTo(OutputStream) 方法,它將會返回寫入給定流的全部內容。
當實體內部含有信息時,使用HttpEntity#getContentType()和HttpEntity#getContentLength()方法將會讀取一些主要的元數據,比方Content-Type和Content-Length這種首部(假設他們可用的話)。因為Content-Type首部可以包括文本MIME類型(像 text/plain 或text/html),它也包括了與MIME類型相相應的字符編碼。HttpEntity#getContentEncoding()方法被用來讀取這些字符編碼。假設相應的首部不存在,則Content-Length的返回值為-1,Content-Type返回值為NULL。假設Content-Type是可用的,一個Header類的對象將會返回。
當我們構建一個具有可用信息的實體時,元數據將會被實體構建器提供。【譯者:我理解的是。如以下樣例中的長度,並沒有聲明,可是可用,是構建器生成的】
StringEntity myEntity = new StringEntity("important message",
ContentType.create("text/plain", "UTF-8"));
System.out.println(myEntity.getContentType());
System.out.println(myEntity.getContentLength());
System.out.println(EntityUtils.toString(myEntity));
System.out.println(EntityUtils.toByteArray(myEntity).length);輸出:
Content-Type: text/plain; charset=utf-8
17
important message
17
1.1.5.確保釋放低級別的資源
為了確保正確的釋放系統資源,你必須關掉與實體與實體相關的的內容流。還必須關掉響應本身。CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
try {
// do something useful
} finally {
instream.close();
}
}
} finally {
response.close();
}關閉內容流和關閉響應的不同點是:前者將會通過消費實體內容保持潛在的連接。而后者迅速的關閉並丟棄連接。
請注意,一旦實體被HttpEntity#writeTo(OutputStream)方法成功地寫入時,也須要確保正確地釋放系統資源。假設方法獲得通過HttpEntity#getContent(),它也須要在一個finally子句中關閉流。
當使用實體時,你能夠使用EntityUtils#consume(HttpEntity)方法來確保實體內容全然被消費而且使潛在的流關閉。
某些情況。整個響應內容的只一小部分須要被取出。會使消費其它剩余內容的性能代價和連接可重用性代價太高,這時能夠通過關閉響應來終止內容流。
【譯者:樣例中能夠看出,實體輸入流只讀取了兩個字節,就關閉了響應,也就是按需讀取,而不是讀取所有響應】
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int byteOne = instream.read();
int byteTwo = instream.read();
// Do not need the rest
}
} finally {
response.close();
} 這樣,連接將不會被重用,它分配的全部級別的資源將會被解除。
1.1.6.消費實體內容
為了消費實體內容,推薦的方式是使用HttpEntity#getContent()或者 HttpEntity#writeTo(OutputStream)方法。HttpClient也提供了一個EntityUtils類,它有幾個靜態方法更easy的從實體中讀取內容或信息。代替了直接讀取java.io.InputStream,你能夠通過這個類的方法取出所有內容體並放入一個String 中或者byte數組中。
但是,強烈不建議使用EntityUtils,除非響應實體來自於信任的HTTPserver而且知道它的長度。【譯者:】
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet("http://localhost/");
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
long len = entity.getContentLength();
if (len != -1 && len < 2048) {
System.out.println(EntityUtils.toString(entity));
} else {
// Stream content out
}
}
} finally {
response.close();
}在某些情況下,多次讀取實體內容是必要的。在這樣的情況下,實體內容必須以一些方式緩沖,內存或者硬盤中。為了達到這個目的,最簡單的方法是把原始的實體用BufferedHttpEntity類包裝起來。這將會使原始實體的內容讀入一個in-memory緩沖區。
全部方式的實體包裝都是代表最原始的那個實體。
CloseableHttpResponse response = <...>
HttpEntity entity = response.getEntity();
if (entity != null) {
entity = new BufferedHttpEntity(entity);
}==================總結=====================
1.經過前面兩節的學習,你已經掌握HttpClient4.5的基本使用方法了~趕快去試一下吧~
【HttpClient4.5實訓】一.GET請求訪問新浪網(非原文教程)點擊打開鏈接
