少年阿賓

          那些青春的歲月

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks
          第六章 高級(jí)主題

          6.1 自定義客戶端連接

          在特定條件下,也許需要來(lái)定制HTTP報(bào)文通過線路傳遞,越過了可能使用的HTTP參數(shù)來(lái)處理非標(biāo)準(zhǔn)不兼容行為的方式。比如,對(duì)于Web爬蟲,它可能需要強(qiáng)制HttpClient接受格式錯(cuò)誤的響應(yīng)頭部信息,來(lái)?yè)尵葓?bào)文的內(nèi)容。

          通常插入一個(gè)自定義的報(bào)文解析器的過程或定制連接實(shí)現(xiàn)需要幾個(gè)步驟:

          提供一個(gè)自定義LineParser/LineFormatter接口實(shí)現(xiàn)。如果需要,實(shí)現(xiàn)報(bào)文解析/格式化邏輯。

          class MyLineParser extends BasicLineParser {
          @Override
          public Header parseHeader(
          final CharArrayBuffer buffer) throws ParseException {
          try {
          return super.parseHeader(buffer);
          } catch (ParseException ex) {
          // 壓制ParseException異常
          return new BasicHeader("invalid", buffer.toString());
          }
          }
          }

          提過一個(gè)自定義的OperatedClientConnection實(shí)現(xiàn)。替換需要自定義的默認(rèn)請(qǐng)求/響應(yīng)解析器,請(qǐng)求/響應(yīng)格式化器。如果需要,實(shí)現(xiàn)不同的報(bào)文寫入/讀取代碼。

          class MyClientConnection extends DefaultClientConnection {
          @Override
          protected HttpMessageParser createResponseParser(
          final SessionInputBuffer buffer,
          final HttpResponseFactory responseFactory,
          final HttpParams params) {
          return new DefaultResponseParser(buffer,
          new MyLineParser(),responseFactory,params);
          }
          }

          為了創(chuàng)建新類的連接,提供一個(gè)自定義的ClientConnectionOperator接口實(shí)現(xiàn)。如果需要,實(shí)現(xiàn)不同的套接字初始化代碼。

          class MyClientConnectionOperator extends
          DefaultClientConnectionOperator {
          public MyClientConnectionOperator(
          final SchemeRegistry sr) {
          super(sr);
          }
          @Override
          public OperatedClientConnection createConnection() {
          return new MyClientConnection();
          }
          }

          為了創(chuàng)建新類的連接操作,提供自定義的ClientConnectionManager接口實(shí)現(xiàn)。

          class MyClientConnManager extends SingleClientConnManager {
          public MyClientConnManager(
          final HttpParams params,
          final SchemeRegistry sr) {
          super(params, sr);
          }
          @Override
          protected ClientConnectionOperator createConnectionOperator(
          final SchemeRegistry sr) {
          return new MyClientConnectionOperator(sr);
          }
          }

          6.2 有狀態(tài)的HTTP連接

          HTTP規(guī)范假設(shè)session狀態(tài)信息通常是以HTTP cookie格式嵌入在HTTP報(bào)文中的,因此HTTP連接通常是無(wú)狀態(tài)的,這個(gè)假設(shè)在現(xiàn)實(shí)生活中通常是不對(duì)的。也有一些情況,當(dāng)HTTP連接使用特定的用戶標(biāo)識(shí)或特定的安全上下文來(lái)創(chuàng)建時(shí),因此不能和其它用戶共享,只能由該用戶重用。這樣的有狀態(tài)的HTTP連接的示例就是NTLM認(rèn)證連接和使用客戶端證書認(rèn)證的SSL連接。

          6.2.1 用戶令牌處理器

          HttpClient依賴UserTokenHandler接口來(lái)決定給定的執(zhí)行上下文是否是用戶指定的。如果這個(gè)上下文是用戶指定的或者如果上下文沒有包含任何資源或關(guān)于當(dāng)前用戶指定詳情而是null,令牌對(duì)象由這個(gè)處理器返回,期望唯一地標(biāo)識(shí)當(dāng)前的用戶。用戶令牌將被用來(lái)保證用戶指定資源不會(huì)和其它用戶來(lái)共享或重用。

          如果它可以從給定的執(zhí)行上下文中來(lái)獲得,UserTokenHandler接口的默認(rèn)實(shí)現(xiàn)是使用主類的一個(gè)實(shí)例來(lái)代表HTTP連接的狀態(tài)對(duì)象。UserTokenHandler將會(huì)使用基于如NTLM或開啟的客戶端認(rèn)證SSL會(huì)話認(rèn)證模式的用戶的主連接。如果二者都不可用,那么就不會(huì)返回令牌。

          如果默認(rèn)的不能滿足它們的需要,用戶可以提供一個(gè)自定義的實(shí)現(xiàn):
          DefaultHttpClient httpclient = new DefaultHttpClient();
          httpclient.setUserTokenHandler(new UserTokenHandler() {
          public Object getUserToken(HttpContext context) {
          return context.getAttribute("my-token");
          }
          });

          6.2.2 用戶令牌和執(zhí)行上下文

          在HTTP請(qǐng)求執(zhí)行的過程中,HttpClient添加了下列和用戶標(biāo)識(shí)相關(guān)的對(duì)象到執(zhí)行上下文中:

          'http.user-token':對(duì)象實(shí)例代表真實(shí)的用戶標(biāo)識(shí),通常期望Principle接口的實(shí)例。

          我們可以在請(qǐng)求被執(zhí)行后,通過檢查本地HTTP上下文的內(nèi)容,發(fā)現(xiàn)是否用于執(zhí)行請(qǐng)求的連接是有狀態(tài)的。
          DefaultHttpClient httpclient = new DefaultHttpClient();
          HttpContext localContext = new BasicHttpContext();
          HttpGet httpget = new HttpGet("http://localhost:8080/");
          HttpResponse response = httpclient.execute(httpget, localContext);
          HttpEntity entity = response.getEntity();
          if (entity != null) {
          entity.consumeContent();
          }
          Object userToken = localContext.getAttribute(ClientContext.USER_TOKEN);
          System.out.println(userToken);
          6.2.2.1 持久化有狀態(tài)的連接
          請(qǐng)注意帶有狀態(tài)對(duì)象的持久化連接僅當(dāng)請(qǐng)求被執(zhí)行時(shí),相同狀態(tài)對(duì)象被綁定到執(zhí)行上下文時(shí)可以被重用。所以,保證相同上下文重用于執(zhí)行隨后的相同用戶,或用戶令牌綁定到之前請(qǐng)求執(zhí)行上下文的HTTP請(qǐng)求是很重要的。
          DefaultHttpClient httpclient = new DefaultHttpClient();
          HttpContext localContext1 = new BasicHttpContext();
          HttpGet httpget1 = new HttpGet("http://localhost:8080/");
          HttpResponse response1 = httpclient.execute(httpget1, localContext1);
          HttpEntity entity1 = response1.getEntity();
          if (entity1 != null) {
          entity1.consumeContent();
          }
          Principal principal = (Principal) localContext1.getAttribute(
          ClientContext.USER_TOKEN);
          HttpContext localContext2 = new BasicHttpContext();
          localContext2.setAttribute(ClientContext.USER_TOKEN, principal);
          HttpGet httpget2 = new HttpGet("http://localhost:8080/");
          HttpResponse response2 = httpclient.execute(httpget2, localContext2);
          HttpEntity entity2 = response2.getEntity();
          if (entity2 != null) {
          entity2.consumeContent();
          }

          轉(zhuǎn)載自:http://www.cnblogs.com/loveyakamoz/archive/2011/07/21/2113251.html
          posted on 2012-09-26 16:45 abin 閱讀(806) 評(píng)論(0)  編輯  收藏 所屬分類: httpClient
          主站蜘蛛池模板: 隆回县| 蒙山县| 昭苏县| 城步| 永和县| 绍兴市| 滨州市| 抚宁县| 永新县| 汝南县| 渝北区| 迁安市| 哈巴河县| 洪江市| 乡城县| 江安县| 洛扎县| 陇川县| 沅陵县| 定陶县| 桂平市| 桓台县| 龙海市| 临海市| 滁州市| 盱眙县| 吴忠市| 永丰县| 榆树市| 蓬安县| 高清| 炉霍县| 二连浩特市| 赞皇县| 原阳县| 教育| 乌拉特中旗| 长岛县| 平塘县| 宜君县| 江西省|