httpclient4中文版幫助文檔_第1頁
httpclient4中文版幫助文檔_第2頁
httpclient4中文版幫助文檔_第3頁
httpclient4中文版幫助文檔_第4頁
httpclient4中文版幫助文檔_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、httpclient4 中文版幫助文檔,最新官方版翻譯版前言超文本傳輸協(xié)議(HTTP)也許是當(dāng)今互聯(lián)網(wǎng)上使用的最重要的協(xié)議了。Web服務(wù),有網(wǎng)絡(luò)功能的設(shè)備和網(wǎng)絡(luò)計算的發(fā)展,都持續(xù)擴展了HTTP協(xié)議的角色,超越了用戶使用的Web瀏覽器范疇,同時,也增加了需要HTTP協(xié)議支持的應(yīng)用程序的數(shù)量。盡管包提供了基本通過HTTP訪問資源的功能,但它沒有提供全面的靈活性和其它很多應(yīng)用程序需要的功能。HttpClient就是尋求彌補這項空白的組件,通過提供一個有效的,保持更新的,功能豐富的軟件包來實現(xiàn)客戶端最新的HTTP標(biāo)準(zhǔn)和建議。為擴展而設(shè)計,同時為基本的HTTP協(xié)議提供強大的支持,HttpClient組件

2、也許就是構(gòu)建HTTP客戶端應(yīng)用程序,比如web瀏覽器,web服務(wù)端,利用或擴展HTTP協(xié)議進行分布式通信的系統(tǒng)的開發(fā)人員的關(guān)注點。1. HttpClient的范圍基于HttpCore/httpcomponents-core/index.html的客戶端HTTP運輸實現(xiàn)庫基于經(jīng)典(阻塞)I/O內(nèi)容無關(guān)2. 什么是HttpClient不能做的HttpClient 不是一個瀏覽器。它是一個客戶端的HTTP通信實現(xiàn)庫。HttpClient的目標(biāo)是發(fā)送和接收HTTP報文。HttpClient不會去緩存內(nèi)容,執(zhí)行 嵌入在HTML頁面中的javascript代碼,猜測內(nèi)

3、容類型,重新格式化請求/重定向URI,或者其它和HTTP運輸無關(guān)的功能。第一章 基礎(chǔ)1.1 執(zhí)行請求 HttpClient 最重要的功能是執(zhí)行HTTP方法。一個HTTP方法的執(zhí)行包含一個或多個HTTP請求/HTTP響應(yīng)交換,通常由HttpClient的內(nèi)部來處理。而期望用戶提供一個要執(zhí)行的請求對象,而HttpClient期望傳輸請求到目標(biāo)服務(wù)器并返回對應(yīng)的響應(yīng)對象,或者當(dāng)執(zhí)行不成功時拋出異常。很自然地,HttpClient API的主要切入點就是定義描述上述規(guī)約的HttpClient接口。這里有一個很簡單的請求執(zhí)行過程的示例:HttpClient httpclient = new Defaul

4、tHttpClient();HttpGet httpget = new HttpGet("http:/localhost/");HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();if (entity != null) InputStream instream = entity.getContent();int l;byte tmp = new byte2048;while (l = instream.read(tmp) != -1) 1.1

5、.1 HTTP請求所有HTTP請求有一個組合了方法名,請求URI和HTTP協(xié)議版本的請求行。HttpClient 支持所有定義在HTTP/1.1版本中的HTTP方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。對于每個方法類 型都有一個特殊的類:HttpGet,HttpHead,HttpPost,HttpPut,HttpDelete,HttpTrace和 HttpOptions。請求的URI是統(tǒng)一資源定位符,它標(biāo)識了應(yīng)用于哪個請求之上的資源。HTTP請求URI包含一個協(xié)議模式,主機名稱,可選的端口,資源路徑,可選的查詢和可選的片段。HttpGet httpge

6、t = new HttpGet("HttpClient提供很多工具方法來簡化創(chuàng)建和修改執(zhí)行URI。URI也可以編程來拼裝:URI uri = URIUtils.createURI("http", "", -1, "/search","q=httpclient&btnG=Google+Search&aq=f&oq=", null);HttpGet httpget = new HttpGet(uri);System.out.println(httpget.getURI();輸出內(nèi)容為:

7、查詢字符串也可以從獨立的參數(shù)中來生成:List<NameValuePair> qparams = new ArrayList<NameValuePair>();qparams.add(new BasicNameValuePair("q", "httpclient");qparams.add(new BasicNameValuePair("btnG", "Google Search");qparams.add(new BasicNameValuePair("aq", &qu

8、ot;f");qparams.add(new BasicNameValuePair("oq", null);URI uri = URIUtils.createURI("http", "", -1, "/search",URLEncodedUtils.format(qparams, "UTF-8"), null);HttpGet httpget = new HttpGet(uri);System.out.println(httpget.getURI();輸出內(nèi)容為:1.1.2 HTTP響

9、應(yīng)HTTP響應(yīng)是由服務(wù)器在接收和解釋請求報文之后返回發(fā)送給客戶端的報文。響應(yīng)報文的第一行包含了協(xié)議版本,之后是數(shù)字狀態(tài)碼和相關(guān)聯(lián)的文本段。HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "OK");System.out.println(response.getProtocolVersion();System.out.println(response.getStatusLine().getStatusCode();System.out.println(re

10、sponse.getStatusLine().getReasonPhrase();System.out.println(response.getStatusLine().toString();輸出內(nèi)容為:HTTP/1.1200OKHTTP/1.1 200 OK1.1.3 處理報文頭部一個HTTP報文可以包含很多描述如內(nèi)容長度,內(nèi)容類型等信息屬性的頭部信息。HttpClient提供獲取,添加,移除和枚舉頭部信息的方法。HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "

11、;OK");response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost");response.addHeader("Set-Cookie","c2=b; path="/", c3=c; domain="localhost"");Header h1 = response.getFirstHeader("Set-Cookie");System.out.println(h1);Head

12、er h2 = response.getLastHeader("Set-Cookie");System.out.println(h2);Header hs = response.getHeaders("Set-Cookie");System.out.println(hs.length);輸出內(nèi)容為:Set-Cookie: c1=a; path=/; domain=localhostSet-Cookie: c2=b; path="/", c3=c; domain="localhost"獲得給定類型的所有頭部信息最有效

13、的方式是使用HeaderIterator接口。HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "OK");response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost");response.addHeader("Set-Cookie","c2=b; path="/", c3=c; domain=&qu

14、ot;localhost"");HeaderIterator it = response.headerIterator("Set-Cookie");while (it.hasNext() System.out.println(it.next();輸出內(nèi)容為:Set-Cookie: c1=a; path=/; domain=localhostSet-Cookie: c2=b; path="/", c3=c; domain="localhost"它也提供解析HTTP報文到獨立頭部信息元素的方法方法。HttpRespon

15、se response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "OK");response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost");response.addHeader("Set-Cookie","c2=b; path="/", c3=c; domain="localhost"");HeaderE

16、lementIterator it = new BasicHeaderElementIterator(response.headerIterator("Set-Cookie");while (it.hasNext() HeaderElement elem = it.nextElement();System.out.println(elem.getName() + " = " + elem.getValue();NameValuePair params = elem.getParameters();for (int i = 0; i < params

17、.length; i+) System.out.println(" " + paramsi);輸出內(nèi)容為:c1 = apath=/domain=localhostc2 = bpath=/c3 = cdomain=localhost1.1.4 HTTP實體HTTP 報文可以攜帶和請求或響應(yīng)相關(guān)的內(nèi)容實體。實體可以在一些請求和響應(yīng)中找到,因為它們也是可選的。使用了實體的請求被稱為封閉實體請求。HTTP規(guī)范定義 了兩種封閉實體的方法:POST和PUT。響應(yīng)通常期望包含一個內(nèi)容實體。這個規(guī)則也有特例,比如HEAD方法的響應(yīng)和204 No Content,304 Not Modifi

18、ed和205 Reset Content響應(yīng)。HttpClient根據(jù)其內(nèi)容出自何處區(qū)分三種類型的實體:streamed流式:內(nèi)容從流中獲得,或者在運行中產(chǎn)生。特別是這種分類包含從HTTP響應(yīng)中獲取的實體。流式實體是不可重復(fù)生成的。self-contained自我包含式:內(nèi)容在內(nèi)存中或通過獨立的連接或其它實體中獲得。自我包含式的實體是可以重復(fù)生成的。這種類型的實體會經(jīng)常用于封閉HTTP請求的實體。wrapping包裝式:內(nèi)容從另外一個實體中獲得。當(dāng)從一個HTTP響應(yīng)中獲取流式內(nèi)容時,這個區(qū)別對于連接管理很重要。對于由應(yīng)用程序創(chuàng)建而且只使用HttpClient發(fā)送的請求實體,流式和自我包含式的不

19、同就不那么重要了。這種情況下,建議考慮如流式這種不能重復(fù)的實體,和可以重復(fù)的自我包含式實體。 重復(fù)實體實體可以重復(fù),意味著它的內(nèi)容可以被多次讀取。這就僅僅是自我包含式的實體了(像ByteArrayEntity或StringEntity)。 使用HTTP實體因為一個實體既可以代表二進制內(nèi)容又可以代表字符內(nèi)容,它也支持字符編碼(支持后者也就是字符內(nèi)容)。實體是當(dāng)使用封閉內(nèi)容執(zhí)行請求,或當(dāng)請求已經(jīng)成功執(zhí)行,或當(dāng)響應(yīng)體結(jié)果發(fā)功到客戶端時創(chuàng)建的。要 從實體中讀取內(nèi)容,可以通過HttpEntity#getContent()方法從輸入流中獲取,這會返回一個java.io.Inpu

20、tStream對 象,或者提供一個輸出流到HttpEntity#writeTo(OutputStream)方法中,這會一次返回所有寫入到給定流中的內(nèi)容。當(dāng) 實體通過一個收到的報文獲取時,HttpEntity#getContentType()方法和 HttpEntity#getContentLength()方法可以用來讀取通用的元數(shù)據(jù),如Content-Type和Content-Length 頭部信息(如果它們是可用的)。因為頭部信息Content-Type可以包含對文本MIME類型的字符編碼,比如text/plain或text /html,HttpEntity#getContentEncodi

21、ng()方法用來讀取這個信息。如果頭部信息不可用,那么就返回長度-1,而對于內(nèi) 容類型返回NULL。如果頭部信息Content-Type是可用的,那么就會返回一個Header對象。當(dāng)為一個傳出報文創(chuàng)建實體時,這個元數(shù)據(jù)不得不通過實體創(chuàng)建器來提供。StringEntity myEntity = new StringEntity("important message","UTF-8");System.out.println(myEntity.getContentType();System.out.println(myEntity.getContentLeng

22、th();System.out.println(EntityUtils.getContentCharSet(myEntity);System.out.println(EntityUtils.toString(myEntity);System.out.println(EntityUtils.toByteArray(myEntity).length);輸出內(nèi)容為Content-Type: text/plain; charset=UTF-817UTF-8important message171.1.5 確保低級別資源釋放當(dāng) 完成一個響應(yīng)實體,那么保證所有實體內(nèi)容已經(jīng)被完全消耗是很重要的,所以連接可以

23、安全的放回到連接池中,而且可以通過連接管理器對后續(xù)的請求重用連接。處 理這個操作的最方便的方法是調(diào)用HttpEntity#consumeContent()方法來消耗流中的任意可用內(nèi)容。HttpClient探測到內(nèi)容 流尾部已經(jīng)到達后,會立即會自動釋放低層連接,并放回到連接管理器。HttpEntity#consumeContent()方法調(diào)用多次也是安全的。也可能會有特殊情況,當(dāng)整個響應(yīng)內(nèi)容的一小部分需要獲取,消耗剩余內(nèi)容而損失性能,還有重用連接的代價太高,則可以僅僅通過調(diào)用HttpUriRequest#abort()方法來中止請求。HttpGet httpget = new HttpGet(&

24、quot;http:/localhost/");HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();if (entity != null) InputStream instream = entity.getContent();int byteOne = instream.read();int byteTwo = instream.read();/ Do not need the resthttpget.abort();連接不會被重用,但是由它持有的所有

25、級別的資源將會被正確釋放。1.1.6 消耗實體內(nèi)容推 薦消耗實體內(nèi)容的方式是使用它的HttpEntity#getContent()或HttpEntity#writeTo(OutputStream)方 法。HttpClient也自帶EntityUtils類,這會暴露出一些靜態(tài)方法,這些方法可以更加容易地從實體中讀取內(nèi)容或信息。代替直接讀取 java.io.InputStream,也可以使用這個類中的方法以字符串/字節(jié)數(shù)組的形式獲取整個內(nèi)容體。然而,EntityUtils的使用是強烈 不鼓勵的,除非響應(yīng)實體源自可靠的HTTP服務(wù)器和已知的長度限制。HttpGet httpget = new Htt

26、pGet("http:/localhost/");HttpResponse response = httpclient.execute(httpget);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在

27、一些情況下可能會不止一次的讀取實體。此時實體內(nèi)容必須以某種方式在內(nèi)存或磁盤上被緩沖起來。最簡單的方法是通過使用BufferedHttpEntity類來包裝源實體完成。這會引起源實體內(nèi)容被讀取到內(nèi)存的緩沖區(qū)中。在其它所有方式中,實體包裝器將會得到源實體。HttpGet httpget = new HttpGet("http:/localhost/");HttpResponse response = httpclient.execute(httpget);HttpEntity entity = response.getEntity();if (entity != null) e

28、ntity = new BufferedHttpEntity(entity);1.1.7 生成實體內(nèi)容HttpClient 提供一些類,它們可以用于生成通過HTTP連接獲得內(nèi)容的有效輸出流。為了封閉實體從HTTP請求中獲得的輸出內(nèi)容,那些類的實例可以和封閉如POST和 PUT請求的實體相關(guān)聯(lián)。HttpClient為很多公用的數(shù)據(jù)容器,比如字符串,字節(jié)數(shù)組,輸入流和文件提供了一些 類:StringEntity,ByteArrayEntity,InputStreamEntity和FileEntity。File file = new File("somefile.txt");Fi

29、leEntity entity = new FileEntity(file, "text/plain; charset="UTF-8"");HttpPost httppost = new HttpPost("http:/localhost/action.do");httppost.setEntity(entity);請 注意InputStreamEntity是不可重復(fù)的,因為它僅僅能從低層數(shù)據(jù)流中讀取一次內(nèi)容。通常來說,我們推薦實現(xiàn)一個定制的HttpEntity 類,這是自我包含式的,用來代替使用通用的InputStreamEntit

30、y。FileEntity也是一個很好的起點。 動態(tài)內(nèi)容實體通 常來說,HTTP實體需要基于特定的執(zhí)行上下文來動態(tài)地生成。通過使用EntityTemplate實體類和ContentProducer接 口,HttpClient提供了動態(tài)實體的支持。內(nèi)容生成器是按照需求生成它們內(nèi)容的對象,將它們寫入到一個輸出流中。它們是每次被請求時來生成內(nèi)容。所 以用EntityTemplate創(chuàng)建的實體通常是自我包含而且可以重復(fù)的。ContentProducer cp = new ContentProducer() public void writeTo(OutputStream outstream

31、) throws IOException Writer writer = new OutputStreamWriter(outstream, "UTF-8");writer.write("<response>");writer.write(" <content>");writer.write(" important stuff");writer.write(" </content>");writer.write("</response>&

32、quot;);writer.flush();HttpEntity entity = new EntityTemplate(cp);HttpPost httppost = new HttpPost("http:/localhost/handler.do");httppost.setEntity(entity); HTML表單許多應(yīng)用程序需要頻繁模擬提交一個HTML表單的過程,比如,為了來記錄一個Web應(yīng)用程序或提交輸出數(shù)據(jù)。HttpClient提供了特殊的實體類UrlEncodedFormEntity來這個滿足過程。List<NameValuePair&g

33、t; formparams = new ArrayList<NameValuePair>();formparams.add(new BasicNameValuePair("param1", "value1");formparams.add(new BasicNameValuePair("param2", "value2");UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");HttpP

34、ost httppost = new HttpPost("http:/localhost/handler.do");httppost.setEntity(entity);UrlEncodedFormEntity實例將會使用URL編碼來編碼參數(shù),生成如下的內(nèi)容:param1=value1&param2=value 內(nèi)容分塊通 常,我們推薦讓HttpClient選擇基于被傳遞的HTTP報文屬性的最適合的編碼轉(zhuǎn)換。這是可能的,但是,設(shè)置 HttpEntity#setChunked()方法為true是通知HttpClient分塊編碼的首選。請注意HttpCl

35、ient將會使用標(biāo)識作為 提示。當(dāng)使用的HTTP協(xié)議版本,如HTTP/1.0版本,不支持分塊編碼時,這個值會被忽略。StringEntity entity = new StringEntity("important message","text/plain; charset="UTF-8"");entity.setChunked(true);HttpPost httppost = new HttpPost("http:/localhost/acrtion.do");httppost.setEntity(entity

36、);1.1.8 響應(yīng)控制器控制響應(yīng)的最簡便和最方便的方式是使用ResponseHandler接口。這個放完完全減輕了用戶關(guān)于連接管理的擔(dān)心。當(dāng)使用ResponseHandler時,HttpClient將會自動關(guān)注并保證釋放連接到連接管理器中去,而不管請求執(zhí)行是否成功或引發(fā)了異常。HttpClient httpclient = new DefaultHttpClient();HttpGet httpget = new HttpGet("http:/localhost/");ResponseHandler<byte> handler = new ResponseHa

37、ndler<byte>() public byte handleResponse(HttpResponse response) throws ClientProtocolException, IOException HttpEntity entity = response.getEntity();if (entity != null) return EntityUtils.toByteArray(entity); else return null;byte response = httpclient.execute(httpget, handler);1.2 HTTP執(zhí)行的環(huán)境最

38、初,HTTP是被設(shè)計成無狀態(tài)的,面向請求-響應(yīng)的協(xié)議。然而,真實的應(yīng)用程序經(jīng)常需要通過一些邏輯相關(guān)的請求-響應(yīng)交換來持久狀態(tài)信息。為了開啟應(yīng)用程 序來維持一個過程狀態(tài),HttpClient允許HTTP請求在一個特定的執(zhí)行環(huán)境中來執(zhí)行,簡稱為HTTP上下文。如果相同的環(huán)境在連續(xù)請求之間重用, 那么多種邏輯相關(guān)的請求可以參與到一個邏輯會話中。HTTP上下文功能和java.util.Map<String,Object>很相似。 它僅僅是任意命名參數(shù)值的集合。應(yīng)用程序可以在請求之前或在檢查上下文執(zhí)行完成之后來填充上下文屬性。在HTTP請求執(zhí)行的這一過程中,HttpClient添加了下列屬性

39、到執(zhí)行上下文中:'http.connection':HttpConnection實例代表了連接到目標(biāo)服務(wù)器的真實連接。'http.target_host':HttpHost實例代表了連接目標(biāo)。'xy_host':如果使用了,HttpHost實例代表了代理連接。'http.request':HttpRequest實例代表了真實的HTTP請求。'http.response':HttpResponse實例代表了真實的HTTP響應(yīng)。'http.request_sent':java.lang.

40、Boolean對象代表了暗示真實請求是否被完全傳送到目標(biāo)連接的標(biāo)識。比如,為了決定最終的重定向目標(biāo),在請求執(zhí)行之后,可以檢查http.target_host屬性的值:DefaultHttpClient httpclient = new DefaultHttpClient();HttpContext localContext = new BasicHttpContext();HttpGet httpget = new HttpGet("HttpResponse response = httpclient.execute(httpget, localContext);HttpHost t

41、arget = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);System.out.println("Final target: " + target);HttpEntity entity = response.getEntity();if (entity != null) entity.consumeContent();輸出內(nèi)容為:Final target: http:/www.google.ch1.3 異常處理HttpClient 能夠拋出兩種類型的異常:在I/O失敗時,如

42、套接字連接超時或被重置的java.io.IOException異常,還有標(biāo)志HTTP請求失敗的信號,如 違反HTTP協(xié)議的HttpException異常。通常I/O錯誤被認為是非致命的和可以恢復(fù)的,而HTTP協(xié)議錯誤則被認為是致命的而且是不能自動恢 復(fù)的。1.3.1 HTTP運輸安全要 理解HTTP協(xié)議并不是對所有類型的應(yīng)用程序都適合的,這一點很重要。HTTP是一個簡單的面向請求/響應(yīng)的協(xié)議,最初被設(shè)計用來支持取回靜態(tài)或動態(tài)生成 的內(nèi)容。它從未向支持事務(wù)性操作方向發(fā)展。比如,如果成功收到和處理請求,HTTP服務(wù)器將會考慮它的其中一部分是否完成,生成一個響應(yīng)并發(fā)送一個狀態(tài)碼 到客戶端。如果客戶端

43、因為讀取超時,請求取消或系統(tǒng)崩潰導(dǎo)致接收響應(yīng)實體失敗時,服務(wù)器不會試圖回滾事務(wù)。如果客戶端決定重新這個請求,那么服務(wù)器將不可 避免地不止一次執(zhí)行這個相同的事務(wù)。在一些情況下,這會導(dǎo)致應(yīng)用數(shù)據(jù)損壞或者不一致的應(yīng)用程序狀態(tài)。盡管HTTP從來都沒有被設(shè)計來支持事務(wù)性處理,但它也能被用作于一個傳輸協(xié)議對關(guān)鍵的任務(wù)應(yīng)用提供被滿足的確定狀態(tài)。要保證HTTP傳輸層的安全,系統(tǒng)必須保證HTTP方法在應(yīng)用層的冪等性。1.3.2 冪等的方法HTTP/1.1 明確地定義了冪等的方法,描述如下方法也可以有“冪等”屬性在那些(除了錯誤或過期問題)N的副作用>0的相同請求和獨立的請求是相同的換句話說,應(yīng)用程序應(yīng)該保

44、證準(zhǔn)備著來處理多個相同方法執(zhí)行的實現(xiàn)。這是可以達到的,比如,通過提供一個獨立的事務(wù)ID和其它避免執(zhí)行相同邏輯操作的方法。請注意這個問題對于HttpClient是不具體的?;趹?yīng)用的瀏覽器特別受和非冪等的HTTP方法相關(guān)的相同問題的限制。HttpClient假設(shè)沒有實體包含方法,比如GET和HEAD是冪等的,而實體包含方法,比如POST和PUT則不是。1.3.3 異常自動恢復(fù)默認情況下,HttpClient會試圖自動從I/O異常中恢復(fù)。默認的自動恢復(fù)機制是受很少一部分已知的異常是安全的這個限制。HttpClient不會從任意邏輯或HTTP協(xié)議錯誤(那些是從HttpException類中派生出的)

45、中恢復(fù)的。HttpClient將會自動重新執(zhí)行那么假設(shè)是冪等的方法。HttpClient將會自動重新執(zhí)行那些由于運輸異常失敗,而HTTP請求仍然被傳送到目標(biāo)服務(wù)器(也就是請求沒有完全被送到服務(wù)器)失敗的方法。HttpClient 將會自動重新執(zhí)行那些已經(jīng)完全被送到服務(wù)器,但是服務(wù)器使用HTTP狀態(tài)碼(服務(wù)器僅僅丟掉連接而不會發(fā)回任何東西)響應(yīng)時失敗的方法。在這種情況下,假 設(shè)請求沒有被服務(wù)器處理,而應(yīng)用程序的狀態(tài)也沒有改變。如果這個假設(shè)可能對于你應(yīng)用程序的目標(biāo)Web服務(wù)器來說不正確,那么就強烈建議提供一個自定義的異 常處理器。1.3.4 請求重試處理為了開啟自定義異?;謴?fù)機制,應(yīng)該提供一個Ht

46、tpRequestRetryHandler接口的實現(xiàn)。DefaultHttpClient httpclient = new DefaultHttpClient();HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() public boolean retryRequest(IOException exception,int executionCount,HttpContext context) if (executionCount >= 5) / 如果超過最大重試次數(shù),那么就不要繼續(xù)了return f

47、alse;if (exception instanceof NoHttpResponseException) / 如果服務(wù)器丟掉了連接,那么就重試return true;if (exception instanceof SSLHandshakeException) / 不要重試SSL握手異常return false;HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);boolean idempotent = !(request instanceof HttpEntityE

48、nclosingRequest);if (idempotent) / 如果請求被認為是冪等的,那么就重試return true;return false;httpclient.setHttpRequestRetryHandler(myRetryHandler);1.4 中止請求在 一些情況下,由于目標(biāo)服務(wù)器的高負載或客戶端有很多活動的請求,那么HTTP請求執(zhí)行會在預(yù)期的時間框內(nèi)而失敗。這時,就可能不得不過早地中止請求,解除 封鎖在I/O執(zhí)行中的線程封鎖。被HttpClient執(zhí)行的HTTP請求可以在執(zhí)行的任意階段通過調(diào)用HttpUriRequest#abort()方 法而中止。這個方法是線程安

49、全的,而且可以從任意線程中調(diào)用。當(dāng)一個HTTP請求被中止時,它的執(zhí)行線程就封鎖在I/O操作中了,而且保證通過拋出 InterruptedIOException異常來解鎖。1.5 HTTP協(xié)議攔截器HTTP 協(xié)議攔截器是一個實現(xiàn)了特定HTPP協(xié)議方面的慣例。通常協(xié)議攔截器希望作用于一個特定頭部信息上,或者一族收到報文的相關(guān)頭部信息,或使用一個特定的頭 部或一族相關(guān)的頭部信息填充發(fā)出的報文。協(xié)議攔截器也可以操縱包含在報文中的內(nèi)容實體,透明的內(nèi)容壓縮/解壓就是一個很好的示例。通常情況下這是由包裝器 實體類使用了“裝飾者”模式來裝飾原始的實體完成的。一些協(xié)議攔截器可以從一個邏輯單元中來結(jié)合。協(xié)議攔截器

50、也可以通過共享信息來共同合作-比如處理狀態(tài)-通過HTTP執(zhí)行上下文。協(xié)議攔截器可以使用HTTP內(nèi)容來為一個或多個連續(xù)的請求存儲一個處理狀態(tài)。通常攔截器執(zhí)行的順序不應(yīng)該和它們基于的特定執(zhí)行上下文狀態(tài)有關(guān)。如果協(xié)議攔截器有相互依存關(guān)系,那么它們必須按特定順序來執(zhí)行,正如它們希望執(zhí)行的順序一樣,它們應(yīng)該在相同的序列中被加到協(xié)議處理器。協(xié)議攔截器必須實現(xiàn)為線程安全的。和Servlet相似,協(xié)議攔截器不應(yīng)該使用實例變量,除非訪問的那些變量是同步的。這個示例給出了本地內(nèi)容在連續(xù)的請求中怎么被用于持久一個處理狀態(tài)的:DefaultHttpClient httpclient = new DefaultHttp

51、Client();HttpContext localContext = new BasicHttpContext();AtomicInteger count = new AtomicInteger(1);localContext.setAttribute("count", count);httpclient.addRequestInterceptor(new HttpRequestInterceptor() public void process(final HttpRequest request,final HttpContext context) throws Http

52、Exception, IOException AtomicInteger count = (AtomicInteger) context.getAttribute("count");request.addHeader("Count", Integer.toString(count.getAndIncrement(););HttpGet httpget = new HttpGet("http:/localhost/");for (int i = 0; i < 10; i+) HttpResponse response = http

53、client.execute(httpget, localContext);HttpEntity entity = response.getEntity();if (entity != null) entity.consumeContent();1.6 HTTP參數(shù)HttpParams 接口代表了定義組件運行時行為的一個不變的值的集合。很多情況下,HttpParams和HttpContext相似。二者之間的主要區(qū)別是它們在運行時 使用的不同。這兩個接口表示了對象的集合,它們被視作為訪問對象值的鍵的Map,但是服務(wù)于不同的目的:HttpParams旨在包含簡單對象:整型,浮點型,字符串,集合,還

54、有運行時不變的對象。HttpParams希望被用在“一次寫入-多處準(zhǔn)備”模式下。HttpContext旨在包含很可能在HTTP報文處理這一過程中發(fā)生改變的復(fù)雜對象HttpParams的目標(biāo)是定義其它組件的行為。通常每一個復(fù)雜的組件都有它自己的HttpParams對象。HttpContext的目標(biāo)是來表示一個HTTP處理的執(zhí)行狀態(tài)。通常相同的執(zhí)行上下文在很多合作的對象中共享。1.6.1 參數(shù)層次在 HTTP請求執(zhí)行過程中,HttpRequest對象的HttpParams是和用于執(zhí)行請求的HttpClient實例的HttpParams聯(lián)系在一 起的。這使得設(shè)置在HTTP請求級別的參數(shù)優(yōu)先于設(shè)置在H

55、TTP客戶端級別的HttpParams。推薦的做法是設(shè)置普通參數(shù)對所有的在HTTP客戶端級 別的HTTP請求共享,而且可以選擇性重寫具體在HTTP請求級別的參數(shù)。DefaultHttpClient httpclient = new DefaultHttpClient();httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_0);httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CH

56、ARSET,"UTF-8");HttpGet httpget = new HttpGet("httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,HttpVersion.HTTP_1_1);httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,Boolean.FALSE);httpclient.addRequestInterceptor(new HttpRequestInterceptor()

57、 public void process(final HttpRequest request,final HttpContext context) throws HttpException, IOException System.out.println(request.getParams().getParameter(CoreProtocolPNames.PROTOCOL_VERSION);System.out.println(request.getParams().getParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET);System.out

58、.println(request.getParams().getParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE);System.out.println(request.getParams().getParameter(CoreProtocolPNames.STRICT_TRANSFER_ENCODING););輸出內(nèi)容為:HTTP/1.1UTF-8falsenull1.6.2 HTTP參數(shù)beanHttpParams 接口允許在處理組件的配置上很大的靈活性。很重要的是,新的參數(shù)可以被引入而不會影響老版本的二進制兼容性。然而,和常規(guī)的Java b

59、ean相比,HttpParams也有一個缺點:HttpParams不能使用DI框架來組合。為了緩解這個限制,HttpClient包含了一些 bean類,它們可以用來按順序使用標(biāo)準(zhǔn)的Java eban慣例初始化HttpParams對象。HttpParams params = new BasicHttpParams();HttpProtocolParamBean paramsBean = new HttpProtocolParamBean(params);paramsBean.setVersion(HttpVersion.HTTP_1_1);paramsBean.setContentCharset("UTF-8");paramsBean.setUseExpectContinue(true);System.out.println(

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論