Natural

           

          (轉)HttpClient基礎

          1.1      執行請求

          HttpClient的最重要的功能是執行HTTP方法。一個HTTP方法的執行涉及到一個或多個HTTP請求或HTTP響應的交流,HttpClient通常是在內部處理的。用戶將提供一個執行請求對象,HttpClient發送請求到目標服務器返回一個相應的響應對象,如果執行失敗則拋出一個異常。所以,HttpClient API的主要切入點是HttpClient的接口,它定義了上述約定。

          下面是一個請求執行過程中的最簡單形式的例子:

          HttpClient httpclient = new DefaultHttpClient();

          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 byte[2048];

              while ((l = instream.read(tmp)) != -1) {

              }

          }

          1.1.1        HTTP請求

          所有的HTTP請求包含一個由請求行組成的一個方法名,一個請求的URI和一個HTTP協議的版本。

          HttpClient的支持在HTTP/1.1規范中定義的所有的HTTP方法:GET, HEAD, POST, PUT, DELETE, TRACE  OPTIONS。每有一個方法都有一個對應的類:HttpGetHttpHeadHttpPost,HttpPutHttpDelete,HttpTraceHttpOptions。所有的這些類均實現了HttpUriRequest接口,故可以作為execute的執行參數使用。請求URI是能夠應用請求的統一資源標識符。 HTTP請求的URI包含一個協議計劃protocol scheme,主機名host name,,可選的端口optional port,資源的路徑resource path,可選的查詢optional query和可選的片段optional fragment。

           

          HttpGet httpget = new HttpGet(

               "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");

          HttpClient提供了一系列實用的方法來簡化創建和修改請求URI。

          URI可以組裝編程:

          URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",

              "q=httpclient&btnG=Google+Search&aq=f&oq=", null);

          HttpGet httpget = new HttpGet(uri);

          System.out.println(httpget.getURI());

          輸出>

          http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=

          查詢字符串也可以通過添加參數列表來生成:

          List<NameValuePair> qparams = new ArrayList<NameValuePair>();

          qparams.add(new BasicNameValuePair("q", "httpclient"));

          qparams.add(new BasicNameValuePair("btnG", "Google Search"));

          qparams.add(new BasicNameValuePair("aq", "f"));

          qparams.add(new BasicNameValuePair("oq", null));

          URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",

              URLEncodedUtils.format(qparams, "UTF-8"), null);

          HttpGet httpget = new HttpGet(uri);

          System.out.println(httpget.getURI());

          輸出>

          http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=

          1.1.2        HTTP響應

          HTTP響應是由服務器收到和解釋一個請求消息后返回給客戶端的消息。該消息的第一行包含遵循的協議版本,他由一個數字狀態代碼及其相關的文本來表示。

          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(response.getStatusLine().getReasonPhrase());

          System.out.println(response.getStatusLine().toString());

          輸出>

          HTTP/1.1

          200

          OK

          HTTP/1.1 200 OK

          1.1.3        Headers處理

          一個HTTP消息可以包含一系列headers參數描述信息,例如內容長度,內容類型等。 HttpClient的提供方法來檢索,添加,刪除和枚舉headers

          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=""localhost""");
          Header h1 = response.getFirstHeader("Set-Cookie");
          System.out.println(h1);
          Header h2 = response.getLastHeader("Set-Cookie");
          System.out.println(h2);
          Header[] hs = response.getHeaders("Set-Cookie");
          System.out.println(hs.length);

          輸出>

          Set-Cookie: c1=a; path=/; domain=localhost

          Set-Cookie: c2=b; path="/", c3=c; domain="localhost"

          2

          最有效獲取所有的給定類型的headers方式是使用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=""localhost""");

          HeaderIterator it = response.headerIterator("Set-Cookie");

          while (it.hasNext()) {

              System.out.println(it.next());

          }

          輸出>

          Set-Cookie: c1=a; path=/; domain=localhost

          Set-Cookie: c2=b; path="/", c3=c; domain="localhost"

          它還提供了方便的方法來解析HTTP消息的單個header元素

          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=""localhost""");

           

          HeaderElementIterator 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.length; i++) {

                  System.out.println(" " + params[i]);

              }

          輸出>

          c1 = a

          path=/

          domain=localhost

          c2 = b

          path=/

          c3 = c

          domain=localhost

          1.1.4   HTTP 實體

          HTTP消息的可以進行內容實體和請求或響應關聯??梢栽谝恍┮蠛鸵恍┗貞姓业綄嶓w,因為它們是可選的。實體內附與請求之中。 HTTP規范定義了兩個實體內附方法:POSTPUT。響應通常將會附上一個內容實體。但是響應HEAD方法和 204 No Content, 304 Not Modified, 205 Reset Content responses 除外。

          HttpClient的區分三種不同實體的地方在于內容來源于:

          streamed流媒體:內容是從收到的流,或在運行中產生的。特別是包括被從HTTP響應收到的實體。流媒體的實體一般不可重復。

          self-contained獨立的:內容是在內存或以從一個連接或其他實體的獨立獲得的。獨立的的實體,一般可重復的。這種類型的實體將主要用于內附在HTTP請求中。

          wrapping包裝:實體內容是從另一個實體獲得。

          當得到一個HTTP響應流的內容的時候,這種區分對于連接管理是很重要的。對于請求實體,通過應用程序來創建和只通過使用的HttpClient發送,流和自載之間差別很小。在這種情況下,建議考慮非重復的流實體,以及那些重復的自載實體。

          1.1.4.1             重復實體

          一個實體可以是可重復的,這意味著它的內容可以被讀取一次以上。唯一有可能是的獨立的實體(如ByteArrayEntityStringEntity())

          1.1.4.2             使用HTTP實體

          由于一個實體能夠表示二進制和字符的內容,它可以提供編碼的支持(支持文字、IE和字符內容)。

          這個實體在執行封閉內容的請求的時候或者在請求成功和響應返回成功的時候被創建。

          若要讀取從實體內容,一可以通過檢索HttpEntitygetContent()方法,它返回一個java.io.InputStream,或一個可以提供一個輸出流的HttpEntitywriteToOutputStream中)方法的輸入流,這將返回已被寫入給定的流的所有內容。

          當通過傳入的消息收到實體,方法HttpEntitygetContentType()和HttpEntitygetContentLength()方法可用于閱讀通用元數據metadata,如Content-Type,Content-Length headers(如果可用)。由于Content-Type header可以包含一個像text/plain或者text/html的文本mime-typescharacter encoding,HttpEntitygetContentEncoding()方法用來讀取此信息。如果headers是不可用,返回的長度是-1,content type并為NUL。如果Content – Type header可用,將返回一個header對象。

          當創建了一個即將卸任的消息實體,該meta data必須提供由該實體的創造者。

          StringEntity myEntity = new StringEntity("important message",

              "UTF-8");

           

          System.out.println(myEntity.getContentType());

          System.out.println(myEntity.getContentLength());

          System.out.println(EntityUtils.getContentCharSet(myEntity));

          System.out.println(EntityUtils.toString(myEntity));

          System.out.println(EntityUtils.toByteArray(myEntity).length);

          stdout >

          Content-Type: text/plain; charset=UTF-8

          17

          UTF-8

          important message

          17

          1.1.5   確保資源釋放

          當響應實體完成之后,重要的是要確保所有的實體內容已被完全消耗,使該連接可以安全地返回到連接池,重新由連接管理器提供給后續請求使用。最簡單的方法是調用HttpEntityconsumeContent()方法來消耗流上的所有可用的內容。當檢測到內容已經達到流末尾的時候,HttpClient會自動釋放底層連接返回到連接管理器。HttpEntityconsumeContent()方法多次調用也是安全的。

          當只有小部分實體響應內容需要被檢索和消費。其余內容,使用可重復的連接性能損失太大,可以簡單地調用HttpUriRequestabort()方法來終止請求。

          HttpGet httpget = new HttpGet("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 rest

              httpget.abort();

          }

          該連接將不可重用,但是所有資源會被釋放。

          1.1.6   獲取實體內容

          獲取實體內容推薦的方法是通過使用HttpEntitygetContent()或HttpEntitywriteToOutputStream中)方法。 HttpClient的還配備了EntityUtils類,它暴露了一些靜態方法,以更輕松地閱讀一個實體的內容或資料。使用這個類的方法和直接使用java.io.InputStream方法不同的是,他可以檢索字符串中的全部內容機構/字節數組。強烈建議不要使用EntityUtils,除非響應實體來自一個可信賴的HTTP服務器和已知的有限長度。

          HttpGet httpget = new HttpGet("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

              }

          }

          在某些情況下,實體內容可能需要能夠讀被多次讀取。在這種情況下實體的內容必須以某種方式被緩沖在內存或磁盤上。最簡單的方法是通過BufferedHttpEntity類來封裝原始實體。原始實體內容可以從內存中的緩沖區來讀取。其他方式封裝實體都包含原始實體。

          HttpGet httpget = new HttpGet("http://localhost/");

          HttpResponse response = httpclient.execute(httpget);

          HttpEntity entity = response.getEntity();

          if (entity != null) {

              entity = new BufferedHttpEntity(entity);

          }

          1.1.7   生產實體內容

          HttpClient提供了一些類可以從HTTP連接內容中獲得效地流。這些類的實例可以與實體內附如POSTPUT請求,以便為即將離任的HTTP請求附上實體內容。 HttpClient的為最常見的數據容器幾類,如串,字節數組輸入流和文件:StringEntity,ByteArrayEntityInputStreamEntityFileEntity

          File file = new File("somefile.txt");

          FileEntity entity = new FileEntity(file, "text/plain; charset=""UTF-8""");

           

          HttpPost httppost = new HttpPost("http://localhost/action.do");

          httppost.setEntity(entity);

          請注意InputStreamEntity是不可重復的,因為它只能從底層數據流中讀取一次。一般來說,建議實現自定義HttpEntity類是自載的,而不是使用通用InputStreamEntity。 FileEntity可以是一個很好的起點。

          1.1.7.1             動態內容實體

          通常的HTTP實體需要在執行上下文的時候動態生成的。 HttpClient的提供使用EntityTemplate實體類和ContentProducer接口支持動態實體。內容制作是通過寫需求的內容到一個輸出流,每次請求的時候都會產生。因此,通過EntityTemplate創建實體通常是獨立的,重復性好。

          ContentProducer cp = new ContentProducer() {

              public void writeTo(OutputStream outstream) 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>");

                  writer.flush();

              }

          };

          HttpEntity entity = new EntityTemplate(cp);

          HttpPost httppost = new HttpPost("http://localhost/handler.do");

          httppost.setEntity(entity);

          1.1.7.2             HTML forms

          許多應用程序經常需要模擬一個HTML表單提交的過程,例如,以登錄到Web應用程序或提交的輸入數據。 HttpClient的實體類UrlEncodedFormEntity可以幫助實現這一步。

          List<NameValuePair> formparams = new ArrayList<NameValuePair>();

          formparams.add(new BasicNameValuePair("param1", "value1"));

          formparams.add(new BasicNameValuePair("param2", "value2"));

          UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");

          HttpPost httppost = new HttpPost("http://localhost/handler.do");

          httppost.setEntity(entity);

          UrlEncodedFormEntity實例將使用 URL編碼的編碼參數,并出示下列內容:

          param1=value1&param2=value2

          1.1.7.3             內容組塊

          一般來說,建議當HTTP消息的發送的時候讓HttpClient的選擇最合適的傳輸編碼。這是可能的,但是,HttpClient首選通過設置HttpEntitysetChunked()為true設置編碼。請注意的HttpClient將使用這個標志作為提示。當使用HTTP協議的版本不支持時候該值將被忽略時,如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);

          1.1.8   響應處理程序

          最簡單和最方便的處理響應方式是通過使用ResponseHandler接口。這種方法完全免除了用戶去擔心連接管理。無論執行請求是否成功或導致異常,HttpClientResponseHandler會確保自動釋放該連接回連接管理器。

          HttpClient httpclient = new DefaultHttpClient();

          HttpGet httpget = new HttpGet("http://localhost/");

           

          ResponseHandler<byte[]> handler = new ResponseHandler<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的執行上下文

          最初的HTTP被設計成一個無狀態,響應,要求面向協議。然而,現實世界應用程序通常需要能夠堅持通過幾個邏輯上相關的請求響應交換狀態信息。為了使應用程序能夠保持狀態,HttpClient允許 HTTP請求在一個特定的上下文中執行,被稱為HTTP的上下文。如果一個邏輯同樣的情況下連續請求之間重用,多個邏輯相關的要求可以參加到會話中,。 HTTP上下文功能類似于java.util.Map<String, Object>。它只是一個任意命名的值的集合??梢栽谡埱髨绦谢蛘邎绦型戤呏笮r炏挛牡臅r候在添加屬性參數到應用程序。

          HTTP請求執行的過程中HttpClient添加屬性到執行上下文:

          'http.connection'HttpConnection實例代表實際連接到目標服務器。

          'http.target_host'HttpHost實例代表連接的目標。

          'http.proxy_host'HttpHost實例代表連接代理,如果使用

          'http.request'HttpRequest實例代表實際的HTTP請求。

          'http.response'HttpResponse實例代表了實際的HTTP響應。

          'http.request_sent'java.lang.Boolean的對象,表示該標志指示是否實際的要求已完全傳輸到連接的目標。

           

          例如,想確定最后的重定向目標,一種方法可以在要求執行之后交驗該http.target_host屬性值:

           

          DefaultHttpClient httpclient = new DefaultHttpClient();

           

          HttpContext localContext = new BasicHttpContext();

          HttpGet httpget = new HttpGet("http://www.google.com/");

           

          HttpResponse response = httpclient.execute(httpget, localContext);

           

          HttpHost target = (HttpHost) localContext.getAttribute(

              ExecutionContext.HTTP_TARGET_HOST);

           

          System.out.println("Final target: " + target);

           

          HttpEntity entity = response.getEntity();

          if (entity != null) {

          entity.consumeContent();

          }

          輸出>

          Final target: http://www.google.ch

          1.3      異常處理

          HttpClient的可以拋出兩種例外情況:在I/O錯誤的時候java.io.IOExceptionsocket timeout或者socket resetHttpException 如違反了HTTP協議的HTTP錯誤故障。通常的I/O錯誤被視為非致命性和可恢復的,而HTTP協議錯誤被認為是致命的錯誤,不能自動收回。

          1.3.1        HTTP傳輸安全

          HTTP協議并沒有適用所有應用。 HTTP是一個簡單的請求/響應協議,最初旨在支持靜態或動態生成的內容檢索。它從未打算支持事務操作。例如,HTTP服 務器將考慮其對履行合同的一部分,如果它在接收和處理請求成功,產生了反應,發出了一個狀態代碼返回給客戶端。該服務器將不作任何嘗試回滾事務,如果客戶 端無法接收的全部原因是讀超時,要求取消或系統崩潰的反應。如果客戶決定重試相同的請求,服務器將不可避免地最終執行相同的交易超過一次。在某些情況下, 這可能導致應用數據損壞或不一致的應用現狀。

          雖然HTTP從來沒有被設計成支持事務處理,它仍然可以作為傳輸協議為應用程序用執行關鍵任務。為了確保HTTP傳輸層安全,系統必須確保冪等的HTTP方法在應用層。

          1.3.2        冪等方法

          HTTP/1.1規范定義冪等方法,

          方法含有冪等屬性 指的是(除了錯誤或過期問題),N>0的相同請求和一個單獨的請求是一樣的。

          換句話說,應用程序應該確保它準備處理的多個執行相同的方法的影響。這可以實現的,例如,通過提供一個獨特的交易ID和避免同一邏輯操作執行的其他方式。

          請注意,此問題不是特定的HttpClient?;跒g覽器應用程序是完全符合相關的HTTP方法非冪等同樣的問題。

          HttpClient的假設非實體內附如GETHEAD是冪等與實體內附 POSTPUT方法不是。

          1.3.3        異常自動恢復

          默認情況下的HttpClient嘗試自動恢復從I / O異常。默認的自動恢復機制是限于一個已知是安全的少數例外。

          HttpClient的將不作任何嘗試從任何邏輯或HTTP協議錯誤(從HttpException類派生的)的恢復。

          HttpClient會自動重試那些被假定為冪等的方法。

          HttpClient會自動重試的方法,傳輸失敗異常的HTTP請求仍然被傳輸到目標服務器

          HttpClient會自動重試那些已經完全傳輸到服務器的方法,但服務器沒有響應的HTTP狀態代碼(服務器只是丟棄不發送任何東西連接)。在這種情況下,假設該請求沒有被服務器和應用程序狀態的處理并沒有改變。如果這種假設可能不適用于您的應用程序的Web服務器是真正的目標,強烈建議提供一個自定義的異常處理程序。

          1.3.4        請求重試處理程序

          為了使自定義的異?;謴蜋C制應該提供一個HttpRequestRetryHandler接口的實現。

          DefaultHttpClient httpclient = new DefaultHttpClient();

           

          HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {

           

              public boolean retryRequest(

                      IOException exception,

                      int executionCount,

                      HttpContext context) {

                  if (executionCount >= 5) {

                      // Do not retry if over max retry count

                      return false;

                  }

                  if (exception instanceof NoHttpResponseException) {

                      // Retry if the server dropped connection on us

                      return true;

                  }

                  if (exception instanceof SSLHandshakeException) {

                      // Do not retry on SSL handshake exception

                      return false;

                  }

                  HttpRequest request = (HttpRequest) context.getAttribute(

                          ExecutionContext.HTTP_REQUEST);

                  boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);

                  if (idempotent) {

                      // Retry if the request is considered idempotent

                      return true;

                  }

                  return false;

              }

           

          };

           

          httpclient.setHttpRequestRetryHandler(myRetryHandler);

          1.4      中止請求

          在某些情況下執行HTTP請求未能完成預期的時間范圍內由于對目標服務器或客戶端發出太多的并發請求的高負荷。在這種情況下,可能有必要提前終止和解除封鎖的要求執行的線程在I / O操作阻塞。 HTTP請求被處決的HttpClient可以在任何援引HttpUriRequestabort()方法執行階段中止。此方法是線程安全的,可以從任何線程調用。當一個HTTP請求被中止它的執行線程阻塞在一個I / O操作是保證解鎖通過拋出一個InterruptedIOException

          1.5      攔截HTTP協議

          HTTP協議的攔截器是一個例程,實現了HTTP協議的具體內容。通常協議攔截行動后,預計一個特定標題或傳入的消息頭相關團體或填充一個特定的頭或一組相關的頭傳出的消息。議定書攔截器還可以操縱的消息封閉的實體內容,透明的內容壓縮/解壓是一個很好的例子。通常這是通過使用'裝飾'的模式,其中一個包裝實體類是用來裝飾的原始實體。幾個協議攔截器可以組合成一個邏輯單元。

          攔截器可以通過合作協議共享信息 - 如處理狀態 - 通過HTTP的執行上下文。攔截器可以使用HTTP協議中的要求來存儲一個或多個連續的請求處理狀態。

           

          通常在這種攔截器都執行不應該的問題,只要他們不依賴于特定國家的執行上下文秩序。如果協議攔截器有相互依存,因此必須在一個特定的順序執行的,他們應該被添加到了他們的預期的執行順序相同的順序協議處理器。

          議定書攔截器必須實現為線程安全的。同樣到Servlet,協議攔截器不應使用實例變量,除非獲得這些變量的同步。

          這個例子說明本地上下文可用于保存請求的處理之間的連續狀態:

          DefaultHttpClient httpclient = new DefaultHttpClient();

           

          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 HttpException, 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 = httpclient.execute(httpget, localContext);

             

              HttpEntity entity = response.getEntity();

              if (entity != null) {

                  entity.consumeContent();

              }

          }

          1.6      HTTP parameters

          HttpParams接口代表一個不可改變的值的集合,定義一個組件在運行時行為。在許多方面是相似的HttpContext HttpParams。兩者的主要區別是他們在運行時使用。代表了兩個接口是作為一個組織的鍵映射對象值對象的集合,而是為不同的目的:

          HttpParams是為了包含簡單的對象:整數,雙打,字符串,集合和對象在運行時保持不變。

          HttpParams預計將用在'寫一次 - 準備許多'模式。 HttpContext的目的是包含很可能發生變異的HTTP消息處理過程中的復雜對象。

          HttpParams目的是確定了其他組件的行為。一般每個復雜的組件都有它自己的HttpParams對象。對HttpContext的目的,是代表了一個HTTP進程的執行狀態。通常是相同的執行上下文之間共享許多合作對象。

          1.6.1        參數層次

          HTTP請求的HttpRequest對象執行HttpParams當然是聯系在一起的用于執行請求的HttpClient的實例HttpParams。這使得在HTTP請求參數水平接管HttpParams優先在HTTP客戶端的水平。建議的做法是通過設置在HTTP客戶端級別的共同所有的HTTP請求參數和選擇性覆蓋在HTTP請求級別的具體參數。

          DefaultHttpClient httpclient = new DefaultHttpClient();

          httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,

              HttpVersion.HTTP_1_0);

          httpclient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET,

              "UTF-8");

          HttpGet httpget = new HttpGet("http://www.google.com/");

          httpget.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,

              HttpVersion.HTTP_1_1);

          httpget.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,

              Boolean.FALSE);

          httpclient.addRequestInterceptor(new HttpRequestInterceptor() {

              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.println(request.getParams().getParameter(

                          CoreProtocolPNames.USE_EXPECT_CONTINUE));

                  System.out.println(request.getParams().getParameter(

                          CoreProtocolPNames.STRICT_TRANSFER_ENCODING));

              }

             

          });

          輸出>

          HTTP/1.1

          UTF-8

          false

          null

          1.6.2        HTTP parameters beans

          HttpParams接口為靈活性的實現在處理組件的配置。最重要的是,新的參數可以引進,而不會影響與舊版本的二進制兼容性。然而,HttpParams也具有一定的缺點相比,常規的Java beanHttpParams不能直接投資框架組裝使用。為了緩解這種限制,HttpClient的包括bean class,可以使用,以初始化HttpParams對象使用標準的Java bean約定的class數目。

          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(params.getParameter(

              CoreProtocolPNames.PROTOCOL_VERSION));

          System.out.println(params.getParameter(

              CoreProtocolPNames.HTTP_CONTENT_CHARSET));

          System.out.println(params.getParameter(

              CoreProtocolPNames.USE_EXPECT_CONTINUE));

          System.out.println(params.getParameter(

              CoreProtocolPNames.USER_AGENT));

          輸出>

          HTTP/1.1

          UTF-8

          false

          null

          1.7        執行HTTP請求參數

          這些參數可以影響到執行請求的過程:

          'http.protocol.version':定義使用HTTP協議的版本,如果沒有就請求對象明確。預計此參數類型ProtocolVersion價值。如果該參數沒有設置HTTP/1.1中會被使用。

          'http.protocol.element-charset':定義用于編碼字符集是HTTP協議分子利用。此參數預計java.lang.String類型的值。如果此參數設置不美的ASCII將被使用。

          'http.protocol.content-charset':定義為每默認用于內容主體編碼字符集。此參數預計java.lang.String類型的值。如果該參數沒有設置的ISO - 8859 - 1將被使用。

          'http.useragent':定義了用戶代理頭的內容。此參數預計java.lang.String類型的值。如果此參數未設置,HttpClient的將自動生成一個值。

          'http.protocol.strict-transfer-encoding':定義是否以無效傳輸編碼頭的反應,應予以拒絕。預計此參數類型java.lang.Boolean的價值。如果該參數沒有設置無效的傳輸編碼值將被忽略。

          'http.protocol.expect-continue':激活期望:為封閉的方法,實體100繼續握手。作者期望的目的:100繼續握手,是讓客戶端發送一個請求主體請求消息,以確定是否愿意到原始服務器之前接受客戶端發送請求的請求(根據請求頭)機構。作者期望使用:100繼續握手會導致一個附有如POSTPUT請求(實體顯著的性能改進),要求在目標服務器的身份驗證。預計:100繼續握手應謹慎使用,因為它可能會導致與HTTP代理服務器的問題和不支持HTTP/1.1協議。預計此參數類型java.lang.Boolean的價值。如果該參數沒有設置的HttpClient將嘗試使用握手。

          'http.protocol.wait-for-continue':定義了以毫秒為單位的時間最長的客戶應該花費100繼續等待響應。預計此參數類型java.lang.Integer價值。如果該參數沒有設置的HttpClient將等待一段時間才能恢復請求的身體傳送確認3秒。

          posted on 2010-09-06 23:57 此號已被刪 閱讀(1071) 評論(0)  編輯  收藏 所屬分類: JAVA

          導航

          統計

          常用鏈接

          留言簿(8)

          隨筆分類(83)

          隨筆檔案(78)

          文章檔案(2)

          相冊

          收藏夾(7)

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 双柏县| 临澧县| 鹤岗市| 闻喜县| 鸡泽县| 温泉县| 宜兴市| 承德县| 新巴尔虎左旗| 肥西县| 南昌市| 彭阳县| 湖口县| 东乡| 榆林市| 如皋市| 德昌县| 天台县| 阿坝| 德清县| 青龙| 雷州市| 习水县| 尉犁县| SHOW| 平阳县| 钟祥市| 孝昌县| 云阳县| 电白县| 宝兴县| 甘孜| 霍城县| 师宗县| 南雄市| 伊金霍洛旗| 漯河市| 垣曲县| 钟祥市| 泰来县| 安国市|