



版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、前言超文本傳輸協(xié)議(HTTP)也許是互聯(lián)網(wǎng)上使用的最重要的協(xié)議了。Web 服務(wù),有網(wǎng)絡(luò)功能的設(shè)備和網(wǎng)絡(luò)計(jì)算的發(fā)展,都持續(xù)擴(kuò)展了 HTTP 協(xié)議的角色,瀏覽器范疇,同時(shí),也增加了需要 HTTP 協(xié)議支持的應(yīng)用程序的數(shù)量。了用戶使用的 Web盡管 包提供了基本通過 HTTP資源的功能,但它沒有提供全面的靈活性和其它很多應(yīng)用程序需要的功能。HttpCnt 就是尋求彌補(bǔ)這項(xiàng)空白的組件,通過提供一個(gè)有效的,包來實(shí)現(xiàn)客戶端的HTTP 標(biāo)準(zhǔn)和建議。保持更新的,功能豐富的為擴(kuò)展而設(shè)計(jì),同時(shí)為基本的 HTTP 協(xié)議提供強(qiáng)大的支持,HttpC nt 組件也許就是構(gòu)建 HTTP 客戶端應(yīng)用程序,比如web 瀏覽器,
2、web 服務(wù)端,利用或擴(kuò)展 HTTP 協(xié)議進(jìn)行分布式通信的系統(tǒng)的開發(fā) 的關(guān)注點(diǎn)。1. HttpCnt 的范圍基于HttpCore實(shí)現(xiàn)庫(kù)基于經(jīng)典(阻塞)I/O內(nèi)容無關(guān).ponents-core/index.html的客戶端 HTTP2.HttpCnt 不能做的HttpCnt 不是一個(gè)瀏覽器。它是一個(gè)客戶端的 HTTP 通信實(shí)現(xiàn)庫(kù)。HttpCnt 的目標(biāo)是發(fā)送和接收 HTTP 報(bào)文。HttpCnt 不會(huì)去緩存內(nèi)容,執(zhí)行 嵌入在 HTML 頁(yè)面中的 javascript代碼,猜測(cè)內(nèi)容類型,重新格式化請(qǐng)求/重定向URI,或者其它和 HTTP第一章 基礎(chǔ)無關(guān)的功能。1.1 執(zhí)行請(qǐng)求HttpCnt 最重要
3、的功能是執(zhí)行 HTTP 方法。一個(gè) HTTP 方法的執(zhí)行包含一個(gè)或多個(gè) HTTP請(qǐng)求/HTTP 響應(yīng)交換,通常由 HttpCnt 的來處理。而期 望用戶提供一個(gè)要執(zhí)行的請(qǐng)求對(duì)象,而 HttpCnt 期望傳輸請(qǐng)求到目標(biāo)服務(wù)器并返回對(duì)應(yīng)的響應(yīng)對(duì)象,或者當(dāng)執(zhí)行不成功時(shí)拋出異常。很自然地,HttpCnt API 的主要切入點(diǎn)就是定義描述上述規(guī)約的 HttpCnt 接口。這里有一個(gè)很簡(jiǎn)單的請(qǐng)求執(zhí)行過程的示例:HttpCnt httpcnt = new DefaultHttpCnt();HttpGet httpget = new HttpGet();HttpResponse response = http
4、cnt.execute(httpget); HttpEntity entity = response.getEntity();if (entity != null) InputStream instream = entity.getContent(); l;byte tmp = new byte2048;while (l = instream.read(tmp) != -1) 1.1.1 HTTP 請(qǐng)求所有 HTTP 請(qǐng)求有一個(gè)組合了方法名,請(qǐng)求 URI 和 HTTP 協(xié)議版本的請(qǐng)求行。HttpCnt 支持所有定義在 HTTP/1.1版本中的 HTTP 方法:GET,HEOST,PUT,DEL
5、ETE,TRACE 和 OPTIONS。對(duì)于每個(gè)方法類 型都有一個(gè)特殊的類:HttpGet,HttpHead,Httpt,HttpPut,HttpDelete,HttpTrace 和 HttpOptions。請(qǐng)求的 URI 是資源定位符,它標(biāo)識(shí)了應(yīng)用于哪個(gè)請(qǐng)求之上的資源。HTTP 請(qǐng)求 URI 包含一個(gè)協(xié)議模式,主機(jī)名稱,可選的端口,資源路徑,可選的查詢和可選的片段。HttpGet httpget = new HttpGet(htt);/search?hl=en&q=httpcnt&btnG=+Search&aq=f&oq=HttpCnt 提供很多工具方法來簡(jiǎn)化創(chuàng)建和修改執(zhí)行URI。URI 也
6、可以編程來拼裝:URI uri = URIUtils.createURI(http, , -1, /search,q=httpcnt&btnG=+Search&aq=f&oq=, null);HttpGet httpget = new HttpGet(uri);System.out.pr輸出內(nèi)容為:httln(httpget.getURI();/search?q=httpcnt&btnG=+Search&aq=f&oq=查詢字符串也可以從獨(dú)立的參數(shù)中來生成:List qparams = new ArrayList();qparams.add(new qparams.add(new qparam
7、s.add(newqparams.add(newameValuePair(q, httpcnt);ameValuePair(btnG, ameValuePair(aq, f); ameValuePair(oq, null);Search);URI uri = URIUtils.createURI(http, URLEncodedUtils.format(qparams, UTF-8), null); HttpGet httpget = new HttpGet(uri); System.out.prln(httpget.getURI();輸出內(nèi)容為:, -1, /search,htt1.1.2
8、HTTP 響應(yīng)/search?q=httpcnt&btnG=+Search&aq=f&oq=HTTP 響應(yīng)是由服務(wù)器在接收和解釋請(qǐng)求報(bào)文之后返回發(fā)送給客戶端的報(bào)文。響應(yīng)報(bào)文的第一行包含了協(xié)議版本,之后是數(shù)字狀態(tài)碼和相關(guān)聯(lián)的文本段。HttpResponse response = new BasicHttpResponse(HttpVer.HTTP_1_1,HttpSus.SC_OK, OK);System.out.pr System.out.pr System.out.pr System.out.pr輸出內(nèi)容為: HTTP/1.1200OKln(response.getProtocolVer()
9、;ln(response.getS ln(response.getSln(response.getSusLine().getSusCode();usLine().getReasonPhrase();usLine().toString();HTTP/1.1 200 OK1.1.3 處理報(bào)文頭部一個(gè) HTTP 報(bào)文可以包含很多描述如內(nèi)容長(zhǎng)度,內(nèi)容類型等信息屬性的頭部信息。HttpCnt 提供獲取,添加,移除和枚舉頭部信息的方法。HttpResponse response = new BasicHttpResponse(HttpVer.HTTP_1_1,HttpSus.SC_OK, OK);resp
10、onse.addHeader(Set-,c1=a; path=/;=localhost);response.addHeader(Set- c2=b; path=/, c3=c; Header h1 = response.getSystem.out.prln(h1);,=localhost); Header(Set-);Header h2 = response.getLastHeader(Set- System.out.prln(h2);Header hs = response.getHeaders(Set-););System.out.pr輸出內(nèi)容為:ln(hs.length);Set-Set
11、-: c1=a; path=/;=localhost: c2=b; path=/, c3=c;=localhost獲得給定類型的所有頭部信息最有效的方式是使用 HeaderIterator 接口。HttpResponse response = new BasicHttpResponse(HttpVer.HTTP_1_1,HttpSus.SC_OK, OK);response.addHeader(Set-,c1=a; path=/;=localhost);response.addHeader(Set-c2=b; path=/, c3=c;,=localhost);HeaderIterator i
12、t = response.headerIterator(Set-);while (isNext() System.out.prln(it.next();輸出內(nèi)容為:Set-Set-: c1=a; path=/;=localhost: c2=b; path=/, c3=c;=localhost它也提供HTTP 報(bào)文到獨(dú)立頭部信息元素的方法方法。HttpResponse response = new BasicHttpResponse(HttpVer.HTTP_1_1,HttpSus.SC_OK, OK);response.addHeader(Set-,c1=a; path=/;=localhos
13、t);response.addHeader(Set-c2=b; path=/, c3=c;,=localhost);HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(Set-);while (isNext() HeaderElemenem = it.nexement();System.out.prln(elem.getName() + = + elem.getValue();NameValuePair params = elem.getParameters();for (i = 0
14、; i params.length; i+) System.out.prln( + paramsi);輸出內(nèi)容為: c1 = a path=/=localhostc2 = b path=/ c3 = c=localhost1.1.4 HTTP 實(shí)體HTTP 報(bào)文可以攜帶和請(qǐng)求或響應(yīng)相關(guān)的內(nèi)容實(shí)體。實(shí)體可以在一些請(qǐng)求和響應(yīng)中找到,因?yàn)樗鼈円彩强蛇x的。使用了實(shí)體的請(qǐng)求被稱為封閉實(shí)體請(qǐng)求。HTTP 規(guī)范定義 了兩種封閉實(shí)體的方法:T 和 PUT。響應(yīng)通常期望包含一個(gè)內(nèi)容實(shí)體。這個(gè)規(guī)則也有特例,比如 HEAD 方法的響應(yīng)和204 No Content,304 Not Modified 和205 Res
15、et Content 響應(yīng)。 HttpCnt 根據(jù)其內(nèi)容出自何處區(qū)分三種類型的實(shí)體:streamed 流式:內(nèi)容從流中獲得,或者在運(yùn)行中產(chǎn)生。特別是這種分類包含從 HTTP 響應(yīng)中獲取的實(shí)體。流式實(shí)體是不可重復(fù)生成的。self-contained 自我包含式:內(nèi)容在內(nèi)存中或通過獨(dú)立的連接或其它實(shí)體中獲得。自我包含式的實(shí)體是可以重復(fù)生成的。這種類型的實(shí)體會(huì)經(jīng)常用于封閉HTTP 請(qǐng)求的實(shí)體。wrap包裝式:內(nèi)容從另外一個(gè)實(shí)體中獲得。當(dāng)從一個(gè)HTTP 響應(yīng)中獲取流式內(nèi)容時(shí),這個(gè)區(qū)別對(duì)于連接管理很重要。對(duì)于由應(yīng)用程序創(chuàng)建而且只使用 HttpC nt 發(fā)送的請(qǐng)求實(shí)體,流式和自我包含式的不同就不那么重要了
16、。這種情況下,建議考慮如流式這種不能重復(fù)的實(shí)體,和可以重復(fù)的自我包含式實(shí)體。 重復(fù)實(shí)體實(shí)體可以重復(fù),意味著它的內(nèi)容可以被多次ByteArrayEntity 或StringEntity)。 使用 HTTP 實(shí)體。這就僅僅是自我包含式的實(shí)體了(像因?yàn)橐粋€(gè)實(shí)體既可以代表二進(jìn)制內(nèi)容又可以代表字符內(nèi)容,它也支持字符編碼(支持后者也就是字符內(nèi)容)。實(shí)體是當(dāng)使用封閉內(nèi)容執(zhí)行請(qǐng)求,或當(dāng)請(qǐng)求已經(jīng)成功執(zhí)行,或當(dāng)響應(yīng)體結(jié)果發(fā)功到客戶端時(shí)創(chuàng)建的。要 從實(shí)體中 內(nèi)容,可以通過 HttpEntity#getContent()方法從輸入流中獲取,這會(huì)返回一個(gè)java.io.InputStream 對(duì) 象,或者提供一個(gè)輸出流
17、到 HttpEntity#writeTo(OutputStream)方法中,這會(huì)一次返回所有寫入到給定流中的內(nèi)容。當(dāng) 實(shí) 體通 過一個(gè) 收到 的報(bào) 文獲 取時(shí), HttpEntity#getContentType() 方法 和HttpEntity#getContentLength() 方法可以用來通用的元數(shù)據(jù), 如 Content-Type 和Content-Length 頭部信息(如果它們是可用的)。因?yàn)轭^部信息 Content-Type 可以包含對(duì)文本MIME 類型的字符編碼,比如text/plain 或text /html,HttpEntity#getContentEncoding()方
18、法用來 這個(gè)信息。如果頭部信息不可用,那么就返回長(zhǎng)度-1,而對(duì)于內(nèi) 容類型返回 NULL。如果頭部信息 Content-Type 是可用的,那么就會(huì)返回一個(gè) Header 對(duì)象。當(dāng)為一個(gè)傳出報(bào)文創(chuàng)建實(shí)體時(shí),這個(gè)元數(shù)據(jù)不得不通過實(shí)體創(chuàng)建器來提供。StringEntity myEntity = new StringEntity(important message, UTF-8);System.out.pr System.out.pr System.out.pr System.out.pr System.out.pr輸出內(nèi)容為ln(myEntity.getContentType(); ln(myEn
19、tity.getContentLength(); ln(EntityUtils.getContentCharSet(myEntity); ln(EntityUtils.toString(myEntity);ln(EntityUtils.toByteArray(myEntity).length);Content-Type: text/plain; charset=UTF-8 17UTF-8important message 171.1.5 確保低級(jí)別資源當(dāng) 完成一個(gè)響應(yīng)實(shí)體,那么保證所有實(shí)體內(nèi)容已經(jīng)被完全消耗是很重要的,所以連接可以安全的放回到連接池中,而且可以通過連接管理器對(duì)后續(xù)的請(qǐng)求重用連接
20、。處 理這個(gè)操作的最方便的方法是調(diào)用 HttpEntity#consumeContent()方法來消耗流中的任意可用內(nèi)容。HttpCnt 探測(cè)到內(nèi)容 流尾部已經(jīng)到達(dá)后,會(huì)立即會(huì)自動(dòng)低層連接,并放回到連接管理器。HttpEntity#consumeContent()方法調(diào)用多次也是安全的。也可能會(huì)有特殊情況,當(dāng)整個(gè)響應(yīng)內(nèi)容的一小部分需要獲取,消耗剩余內(nèi)容而損失性能,還有重用連接的代價(jià)太高,則可以僅僅通過調(diào)用HttpUriRequest#abort()方法來中止請(qǐng)求。HttpGet httpget = new HttpGet();HttpResponse response = httpcnt.ex
21、ecute(httpget); HttpEntity entity = response.getEntity();if (entity != null) InputStream instream = entity.getContent(); byteOne = instream.read();byteTwo = instream.read();/ Do not need the rest httpget.abort();連接不會(huì)被重用,但是由它持有的所有級(jí)別的資源將會(huì)被正確1.1.6 消耗實(shí)體內(nèi)容。消 耗 實(shí) 體 內(nèi) 容 的 方 式 是 使 用 它 的 HttpEntity#getConten
22、t() 或HttpEntity#writeTo(OutputStream)方 法。HttpC nt 也自帶 EntityUtils 類,這會(huì)出一些靜態(tài)方法, 這些方法可以更加容易地從實(shí)體中內(nèi)容或信息。代替直接java.io.InputStream,也可以使用這個(gè)類中的方法以字符串/字節(jié)數(shù)組的形式獲取整個(gè)內(nèi)容體。然而,EntityUtils 的使用是強(qiáng)烈 不鼓勵(lì)的,除非響應(yīng)實(shí)體源自可靠的 HTTP 服務(wù)器和已知的長(zhǎng)度限制。HttpGet httpget = new HttpGet();HttpResponse response = httpcnt.execute(httpget); HttpEn
23、tity entity = response.getEntity();if (entity != null) long len = entity.getContentLength(); if (len != -1 & len 2048) System.out.prln(EntityUtils.toString(entity); else / Stream content out在一些情況下可能會(huì)不止一次的實(shí)體。此時(shí)實(shí)體內(nèi)容必須以某種方式在內(nèi)存或磁盤上被緩沖起來。最簡(jiǎn)單的方法是通過使用 BufferedHttpEntity 類來包裝源實(shí)體完成。這會(huì)引實(shí)體內(nèi)容被到內(nèi)存的緩沖區(qū)中。在其它所有方式中,
24、實(shí)體包裝器將會(huì)得到源實(shí)體。HttpGet httpget = new HttpGet();HttpResponse response = httpcnt.execute(httpget); HttpEntity entity = response.getEntity();if (entity != null) entity = new BufferedHttpEntity(entity);1.1.7 生成實(shí)體內(nèi)容HttpCnt 提供一些類,它們可以用于生成通過 HTTP 連接獲得內(nèi)容的有效輸出流。為了封閉實(shí)體從 HTTP 請(qǐng)求中獲得的輸出內(nèi)容,那些類的實(shí)例可以和封閉如T 和 PUT 請(qǐng)求的實(shí)體
25、相關(guān)聯(lián)。HttpCnt 為很多公用的數(shù)據(jù)容器,比如字符串,字節(jié)數(shù)組,輸入流和文件提供了一些 類:StringEntity,ByteArrayEntity,InputStreamEntity 和 FileEntity。File file = new File(somefile.txt);FileEntity entity = new FileEntity(file, text/plain; charset=UTF-8);Httphttpt httpt = new Httpt();t.setEntity(entity);請(qǐng) 注意 InputStreamEntity 是不可重復(fù)的,因?yàn)樗鼉H僅能從低層
26、數(shù)據(jù)流中一次內(nèi)容。通實(shí)現(xiàn)一個(gè)定制的 HttpEntity 類,這是自我包含式的,用來代替使用通用常來說,的 InputStreamEntity。FileEntity 也是一個(gè)很好的起點(diǎn)。 動(dòng)態(tài)內(nèi)容實(shí)體通 常來說,HTTP 實(shí)體需要基于特定的執(zhí)行上下文來動(dòng)態(tài)地生成。通過使用 EntityTemplate實(shí)體類和 ContentProducer 接 口,HttpCnt 提供了動(dòng)態(tài)實(shí)體的支持。內(nèi)容是按照需求生成它們內(nèi)容的對(duì)象,將它們寫入到一個(gè)輸出流中。它們是每次被請(qǐng)求時(shí)來生成內(nèi)容。所以用 EntityTemplate 創(chuàng)建的實(shí)體通常是自我包含而且可以重復(fù)的。ContentProducer cp =
27、new ContentProducer() public void writeTo(OutputStream outstream) throws IOException Writer writer = new OutputStreamWriter(outstream, UTF-8);writer.write(); writer.write( ); writer.write( important stuff); writer.write( ); writer.write(); writer.flush();HttpEntity entity = new EntityTemplate(cp);Ht
28、tphttpt httpt = new Httpt();t.setEntity(entity); HTML 表單許多應(yīng)用程序需要頻繁模擬提交一個(gè) HTML 表單的過程,比如,為了來一個(gè) Web 應(yīng)用程序或提交輸出數(shù)據(jù)。HttpCnt 提供了特殊的實(shí)體類 UrlEncodedFormEntity 來這個(gè)滿足過程。List formparams = new ArrayList();formparams.add(newformparams.add(newameValuePair(param1, value1);ameValuePair(param2, value2);UrlEncodedFormEn
29、tity entity = new UrlEncodedFormEntity(formparams, UTF-8);Httphttpt httpt = new Httpt();t.setEntity(entity);UrlEncodedFormEntity 實(shí)例將會(huì)使用URL 編碼來編碼參數(shù),生成如下的內(nèi)容:param1=value1¶m2=value2 內(nèi)容分塊讓 HttpCnt 選擇基于被傳遞的 HTTP 報(bào)文屬性的最適合的編碼轉(zhuǎn)換。這通 常,是可能的,但是,設(shè)置 HttpEntity#setCked()方法為 true 是通知 HttpCnt 分塊編碼的首選。請(qǐng)注意HttpCnt
30、 將會(huì)使用標(biāo)識(shí)作為 提示。當(dāng)使用的 HTTP 協(xié)議版本,如HTTP/1.0版本,不支持分塊編碼時(shí),這個(gè)值會(huì)被忽略。StringEntity entity = new StringEntity(important message, text/plain; charset=UTF-8);entity.setCked(true);t = new HttpHttphttp 1.1.8t httpt();t.setEntity(entity);響應(yīng)控制器控制響應(yīng)的最簡(jiǎn)便和最方便的方式是使用 ResponseHandler 接口。這個(gè)放完完全減輕了用戶關(guān)于連接管理的擔(dān)心。當(dāng)使用 ResponseHandl
31、er 時(shí),HttpCnt 將會(huì)自動(dòng)關(guān)注連接到連接管理器中去,而不管請(qǐng)求執(zhí)行是否成功或HttpCnt httpcnt = new DefaultHttpCnt();了異常。HttpGet httpget = new HttpGet();ResponseHandler handler = new ResponseHandler() public byte handleResponse(HttpResponse response) throws CntProtocolException, IOException HttpEntity entity = response.getEntity();if
32、(entity != null) return EntityUtils.toByteArray(entity); else return null;byte response = httpcnt.execute(httpget, handler);1.2 HTTP 執(zhí)行的環(huán)境最 初,HTTP 是被設(shè)計(jì)成無狀態(tài)的,面向請(qǐng)求-響應(yīng)的協(xié)議。然而,真實(shí)的應(yīng)用程序經(jīng)常需要通過一些邏輯相關(guān)的請(qǐng)求-響應(yīng)交換來持久狀態(tài)信息。為了開啟應(yīng)用程 序來維持一個(gè)過程狀態(tài),HttpC nt 允許 HTTP 請(qǐng)求在一個(gè)特定的執(zhí)行環(huán)境中來執(zhí)行,簡(jiǎn)稱為 HTTP 上下文。如果相同的環(huán)境在連續(xù)請(qǐng)求之間重用, 那么多種邏輯相關(guān)的請(qǐng)
33、求可以參與到一個(gè)邏輯會(huì)話中。HTTP 上下文功能和 java.util.Map很相似。 它僅僅是任意命名參數(shù)值的集合。應(yīng)用程序可以在請(qǐng)求之前或在檢查上下文執(zhí)行完成之后來填充上下文屬性。在 HTTP 請(qǐng)求執(zhí)行的這一過程中,HttpC nt 添加了下列屬性到執(zhí)行上下文中:http.connection:HttpConnection 實(shí)例代表了連接到目標(biāo)服務(wù)器的真實(shí)連接。http._host:HttpHost 實(shí)例代表了連接目標(biāo)。xy_host:如果使用了,HttpHost 實(shí)例代表了連接。http.request:HttpRequest 實(shí)例代表了真實(shí)的 HTTP 請(qǐng)求。http.response
34、:HttpResponse 實(shí)例代表了真實(shí)的HTTP 響應(yīng)。http.request_sent:java.lang.接的標(biāo)識(shí)。比如,為了決定最終的重定向目標(biāo),在請(qǐng)求執(zhí)行之后,可以檢查 http. DefaultHttpCnt httpcnt = new DefaultHttpCnt();HttpContext localContext = new BasicHttpContext();對(duì)象代表了暗示真實(shí)請(qǐng)求是否被完全傳送到目標(biāo)連_host 屬性的值:HttpGet httpget = new HttpGet(htt/);HttpResponse response = httpcnt.execu
35、te(httpget, localContext);HttpHost= (HttpHost) localContext.getribute(ExecutionContext.HTTP_System.out.prln(Final_HOST);: +);HttpEntity entity = response.getEntity(); if (entity != null) entity.consumeContent();輸出內(nèi)容為:Final:1.3 異常處理HttpCnt 能夠拋出兩種類型的異常:在 I/O 失敗時(shí),如套接字連接超時(shí)或被重置的java.io.IOException 異常,還有標(biāo)
36、志 HTTP 請(qǐng)求失敗的信號(hào),如HTTP 協(xié)議的HttpException 異常。通常 I/O 錯(cuò)誤被認(rèn)為是非致命的和可以恢復(fù)的,而 HTTP 協(xié)議錯(cuò)誤則被認(rèn)為是致命的而且是不能自動(dòng)恢 復(fù)的。1.3.1 HTTP安全要 理解 HTTP 協(xié)議并不是對(duì)所有類型的應(yīng)用程序都適合的,這一點(diǎn)很重要。HTTP 是一個(gè)簡(jiǎn)單的面向請(qǐng)求/響應(yīng)的協(xié)議,最初被設(shè)計(jì)用來支持取回靜態(tài)或動(dòng)態(tài)生成 的內(nèi)容。它從未向支持事務(wù)性操作方向發(fā)展。比如,如果成功收到和處理請(qǐng)求,HTTP 服務(wù)器將會(huì)考慮它的其中一部分是否完成,生成一個(gè)響應(yīng)并發(fā)送一個(gè)狀態(tài)碼 到客戶端。如果客戶端因?yàn)槌瑫r(shí),請(qǐng)求取消或系統(tǒng)導(dǎo)致接收響應(yīng)實(shí)體失敗時(shí),服務(wù)器不會(huì)試
37、圖回滾事務(wù)。如果客戶端決定重新這個(gè)請(qǐng)求,那么服務(wù)器將不可 避免地不止一次執(zhí)行這個(gè)相同的事務(wù)。在一些情況下,這會(huì)導(dǎo)致應(yīng)用數(shù)據(jù)損壞或者不一致的應(yīng)用程序狀態(tài)。盡管 HTTP 從來都沒有被設(shè)計(jì)來支持事務(wù)性處理,但它也能被用作于一個(gè)傳輸協(xié)議對(duì)關(guān)鍵的任務(wù)應(yīng)用提供被滿足的確定狀態(tài)。要保證 HTTP 傳輸層的安全,系統(tǒng)必須保證 HTTP 方法在應(yīng)用層的冪等性。1.3.2 冪等的方法HTTP/1.1 明確地定義了冪等的方法,描述如下方法也可以有“冪等”屬性在那些(除了錯(cuò)誤或過期問題)N 的副作用0的相同請(qǐng)求和獨(dú)立的請(qǐng)求是相同的換句話說,應(yīng)用程序應(yīng)該保證準(zhǔn)備著來處理多個(gè)相同方法執(zhí)行的實(shí)現(xiàn)。這是可以達(dá)到的,比如,通
38、過提供一個(gè)獨(dú)立的事務(wù) ID 和其它避免執(zhí)行相同邏輯操作的方法。請(qǐng)注意這個(gè)問題對(duì)于HttpCnt 是不具體的。基于應(yīng)用的瀏覽器特別受和非冪等的 HTTP 方法相關(guān)的相同問題的限制。HttpCnt 假設(shè)沒有實(shí)體包含方法,比如 GET 和 HEAD 是冪等的,而實(shí)體包含方法,比如T 和 PUT 則不是。1.3.3 異常自動(dòng)恢復(fù)默認(rèn)情況下,HttpCnt 會(huì)試圖自動(dòng)從 I/O 異常中恢復(fù)。默認(rèn)的自動(dòng)恢復(fù)機(jī)制是受很少一部分已知的異常是安全的這個(gè)限制。HttpCnt 不會(huì)從任意邏輯或 HTTP 協(xié)議錯(cuò)誤(那些是從 HttpException 類中派生出的)中恢復(fù)的。HttpCnt 將會(huì)自動(dòng)重新執(zhí)行那么假設(shè)
39、是冪等的方法。HttpCnt 將會(huì)自動(dòng)重新執(zhí)行那些由于異常失敗,而 HTTP 請(qǐng)求仍然被傳送到目標(biāo)服務(wù)器(也就是請(qǐng)求沒有完全被送到服務(wù)器)失敗的方法。HttpC nt 將會(huì)自動(dòng)重新執(zhí)行那些已經(jīng)完全被送到服務(wù)器,但是服務(wù)器使用HTTP 狀態(tài)碼(服務(wù)器僅僅丟掉連接而不會(huì)發(fā)回任何東西)響應(yīng)時(shí)失敗的方法。在這種情況下,假 設(shè)請(qǐng)求沒有被服務(wù)器處理,而應(yīng)用程序的狀態(tài)也沒有改變。如果這個(gè)假設(shè)可能對(duì)于你應(yīng)用程序的目標(biāo) Web 服務(wù)器來說不正確,那么就強(qiáng)烈建議提供一個(gè)自定義的異 常處理器。1.3.4 請(qǐng)求重試處理為了開啟自定義異常恢復(fù)機(jī)制,應(yīng)該提供一個(gè)HttpRequestRetryHandler 接口的實(shí)現(xiàn)。
40、DefaultHttpCnt httpcnt = new DefaultHttpCnt(); HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() publicretryRequest(IOException exception,executionCount,HttpContext context) if (executionCount = 5) / 如果超過最大重試次數(shù),那么就不要繼續(xù)了return false;if (exception instanceof NoHttpResponseExceptio
41、n) / 如果服務(wù)器丟掉了連接,那么就重試return true;if (exception instanceof SSLHandshakeException) / 不要重試 SSL 握手異常return false;HttpRequest request = (HttpRequest) context.geExecutionContext.HTTP_REQUEST);tribute(idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) / 如果請(qǐng)求被認(rèn)為是冪等的,那么就重試return t
42、rue;return false;httpcnt.setHttpRequestRetryHandler(myRetryHandler);1.4 中止請(qǐng)求在 一些情況下,由于目標(biāo)服務(wù)器的高負(fù)載或客戶端有很多活動(dòng)的請(qǐng)求,那么 HTTP 請(qǐng)求執(zhí)在 I/O 執(zhí)行會(huì)在預(yù)期的時(shí)間框內(nèi)而失敗。這時(shí),就可能不得不過早地中止請(qǐng)求,解除。被 HttpC nt 執(zhí)行的 HTTP 請(qǐng)求可以在執(zhí)行的任意階段通過調(diào)用行中的線程HttpUriRequest#abort()方 法而中止。這個(gè)方法是線程安全的,而且可以從任意線程中調(diào)用。當(dāng)一個(gè) HTTP 請(qǐng)求被中止時(shí),它的執(zhí)行線程就在 I/O 操作中了,而且保證通過拋出erru
43、ptedIOException 異常來1.5 HTTP 協(xié)議器。HTTP 協(xié)議器是一個(gè)實(shí)現(xiàn)了特定 HTPP 協(xié)議方面的慣例。通常協(xié)議器希望作用于一個(gè)特定頭部信息上,或者一族收到報(bào)文的相關(guān)頭部信息,或使用一個(gè)特定的頭 部或一族相關(guān)的頭部信息填充發(fā)出的報(bào)文。協(xié)議器也可以包含在報(bào)文中的內(nèi)容實(shí)體,透明的內(nèi)容壓縮/解壓就是一個(gè)很好的示例。通常情況下這是由包裝器 實(shí)體類使用了“裝飾者”模式來裝飾原始的實(shí)體完成的。一些協(xié)議器可以從一個(gè)邏輯單元中來結(jié)合。協(xié)議器也可以通過共享信息來共同合作-比如處理狀態(tài)-通過HTTP 執(zhí)行上下文。協(xié)議攔截器可以使用 HTTP 內(nèi)容來為一個(gè)或多個(gè)連續(xù)的請(qǐng)求一個(gè)處理狀態(tài)。通常器執(zhí)行
44、的順序不應(yīng)該和它們基于的特定執(zhí)行上下文狀態(tài)有關(guān)。如果協(xié)議器有相互依存關(guān)系,那么它們必須按特定順序來執(zhí)行,正如它們希望執(zhí)行的順序一樣,它們應(yīng)該在相同的序列中被加到協(xié)議處理器。協(xié)議器必須實(shí)現(xiàn)為線程安全的。和Servlet 相似,協(xié)議器不應(yīng)該使用實(shí)例變量,除非的那些變量是同步的。這個(gè)示例給出了本地內(nèi)容在連續(xù)的請(qǐng)求中怎么被用于持久一個(gè)處理狀態(tài)的:DefaultHttpCnt httpcnt = new DefaultHttpCnt(); HttpContext localContext = new BasicHttpContext();Atomiceger count = new Atomiceger
45、(1);localContext.setribute(count, count);httpcnt.addRequesterceptor(new HttpRequesterceptor() public void pros(final HttpRequest request,final HttpContext context) throws HttpException, IOException Atomiceger count = (Atomiceger) context.getribute(count);request.addHeader(Count,);eger.toString(count
46、.getAndIncrement();HttpGet httpget = new HttpGet();for (i = 0; i 10; i+) HttpResponse response = httpcnt.execute(httpget, localContext); HttpEntity entity = response.getEntity();if (entity != null) entity.consumeContent();1.6 HTTP 參數(shù)HttpParams 接口代表了定義組件運(yùn)行時(shí)行為的一個(gè)不變的值的集合。很多情況下, HttpParams 和HttpContext
47、相似。二者之間的主要區(qū)別是它們?cè)谶\(yùn)行時(shí) 使用的不同。這兩個(gè)接口表示了對(duì)象的集合,它們被視作為對(duì)象值的鍵的 Map,但是服務(wù)于不同的目的: HttpParams 旨在包含簡(jiǎn)單對(duì)象:整型,浮點(diǎn)型,字符串,集合,還有運(yùn)行時(shí)不變的對(duì)象。 HttpParams 希望被用在“一次寫入-多處準(zhǔn)備”模式下。HttpContext 旨在包含很可能在 HTTP 報(bào)文處理這一過程中發(fā)生改變的復(fù)雜對(duì)象HttpParams 的目標(biāo)是定義其它組件的行為。通常每一個(gè)復(fù)雜的組件都有它自己的HttpParams 對(duì)象。HttpContext 的目標(biāo)是來表示一個(gè)HTTP 處理的執(zhí)行狀態(tài)。通常相同的執(zhí)行上下文在很多合作的對(duì)象1.6
48、.1 參數(shù)層次享。在 HTTP 請(qǐng)求執(zhí)行過程中,HttpRequest 對(duì)象的HttpParams 是和用于執(zhí)行請(qǐng)求的HttpCnt實(shí)例的HttpParams 聯(lián)系在一 起的。這使得設(shè)置在HTTP 請(qǐng)求級(jí)別的參數(shù)優(yōu)先于設(shè)置在HTTP客戶端級(jí)別的 HttpParams。的做法是設(shè)置普通參數(shù)對(duì)所有的在 HTTP 客戶端級(jí) 別的HTTP 請(qǐng)求共享,而且可以選擇性重寫具體在 HTTP 請(qǐng)求級(jí)別的參數(shù)。DefaultHttpCnt httpcnt = new DefaultHttpCnt();httpcnt.getParams().setParameter(CoreProtocolPNames.PROT
49、OCOL_VER ion.HTTP_1_0);,HttpVershttpcnt.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,UTF-8);HttpGet httpget = new HttpGet(htt/);httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERn.HTTP_1_1);,HttpVersiohttpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CO
50、NTINUE,Boolean.FALSE);httpcnt.addRequesterceptor(new HttpRequesterceptor() public void pros(final HttpRequest request,final HttpContext context) throws HttpException, IOException System.out.prln(request.getParams().getParameter(CoreProtocolPNames.PROTOCOL_VER);System.out.prln(request.getParams().get
51、Parameter( CoreProtocolPNames.HTTP_CONTENT_CHARSET); System.out.prln(request.getParams().getParameter( CoreProtocolPNames.USE_EXPECT_CONTINUE); System.out.prln(request.getParams().getParameter( CoreProtocolPNames.STRICT_TRANSFER_ENCODING););輸出內(nèi)容為: HTTP/1.1 UTF-8false null1.6.2 HTTP 參數(shù) beanHttpParams 接口允許在處理組件的配置上很大的靈活性。很
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 勞動(dòng)合同法在企業(yè)的實(shí)施調(diào)查報(bào)告(2025年版)
- 2025年股權(quán)轉(zhuǎn)讓框架協(xié)議
- 2025年離婚協(xié)議書兩個(gè)小孩模板
- 【單元重點(diǎn)難點(diǎn)】譯林版(三起)英語(yǔ)三年級(jí)上冊(cè)Unit-7-單元復(fù)習(xí)(知識(shí)梳理檢測(cè))-(含解析)
- 2025年河北省邢臺(tái)市單招職業(yè)適應(yīng)性測(cè)試題庫(kù)學(xué)生專用
- 2024年運(yùn)載火箭遙測(cè)系統(tǒng)檢測(cè)設(shè)備項(xiàng)目資金需求報(bào)告代可行性研究報(bào)告
- 第九章 第2節(jié) 液體的壓強(qiáng)(教學(xué)設(shè)計(jì))2024-2025學(xué)年人教版(2024)物理八年級(jí)下冊(cè)
- 2025年??谑袉握新殬I(yè)傾向性測(cè)試題庫(kù)參考答案
- 2025年廣東省外語(yǔ)藝術(shù)職業(yè)學(xué)院?jiǎn)握新殬I(yè)適應(yīng)性測(cè)試題庫(kù)一套
- 《小數(shù)除法-誰(shuí)打電話時(shí)間長(zhǎng)》(教學(xué)設(shè)計(jì))-2024-2025學(xué)年五年級(jí)上冊(cè)數(shù)學(xué)北師大版
- 十堰2024年湖北十堰市茅箭區(qū)教育局所屬學(xué)校招聘教師134人筆試歷年典型考題及考點(diǎn)附答案解析
- 《陸上風(fēng)電場(chǎng)工程概算定額》NBT 31010-2019
- 展會(huì)展中營(yíng)銷方案
- 2024屆遼寧省沈陽(yáng)市名校中考四?;瘜W(xué)試題含答案解析
- 2024年新高考改革方案政策
- 2024年許昌職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫(kù)及答案解析
- 《新媒體創(chuàng)意短視頻制作》課件-運(yùn)動(dòng)短視頻制作關(guān)鍵技術(shù)
- JTGT F20-2015 公路路面基層施工技術(shù)細(xì)則
- 7S培訓(xùn)管理教材課件(-28張)
- 過橋資金計(jì)劃書
- 小學(xué)數(shù)學(xué)計(jì)算練習(xí)-一年級(jí)上學(xué)期口算練習(xí)(600題打印版)
評(píng)論
0/150
提交評(píng)論