Jason ---分享,共同進(jìn)步

          激情成就夢(mèng)想,努力創(chuàng)造未來
          隨筆 - 53, 文章 - 1, 評(píng)論 - 45, 引用 - 0
          數(shù)據(jù)加載中……

          httpclient (2)

          根據(jù)以上步驟,我們來編寫用GET方法來取得某網(wǎng)頁(yè)內(nèi)容的代碼。

          • 大部分情況下 HttpClient 默認(rèn)的構(gòu)造函數(shù)已經(jīng)足夠使用。
            HttpClient httpClient = new HttpClient();
                            

          • 創(chuàng)建GET方法的實(shí)例。在GET方法的構(gòu)造函數(shù)中傳入待連接的地址即可。用GetMethod將會(huì)自動(dòng)處理轉(zhuǎn)發(fā)過程,如果想要把自動(dòng)處理轉(zhuǎn)發(fā)過程去掉的話,可以調(diào)用方法setFollowRedirects(false)。
            GetMethod getMethod = new GetMethod("http://www.ibm.com/");
                            

          • 調(diào)用實(shí)例httpClient的executeMethod方法來執(zhí)行g(shù)etMethod。由于是執(zhí)行在網(wǎng)絡(luò)上的程序,在運(yùn)行executeMethod方法的時(shí)候,需要處理兩個(gè)異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是在構(gòu)造getMethod的時(shí)候傳入的協(xié)議不對(duì),比如不小心將"http"寫成"htp",或者服務(wù)器端返回的內(nèi)容不正常等,并且該異常發(fā)生是不可恢復(fù)的;第二種異常一般是由于網(wǎng)絡(luò)原因引起的異常,對(duì)于這種異常 (IOException),HttpClient會(huì)根據(jù)你指定的恢復(fù)策略自動(dòng)試著重新執(zhí)行executeMethod方法。HttpClient的恢復(fù)策略可以自定義(通過實(shí)現(xiàn)接口HttpMethodRetryHandler來實(shí)現(xiàn))。通過httpClient的方法setParameter設(shè)置你實(shí)現(xiàn)的恢復(fù)策略,本文中使用的是系統(tǒng)提供的默認(rèn)恢復(fù)策略,該策略在碰到第二類異常的時(shí)候?qū)⒆詣?dòng)重試3次。executeMethod返回值是一個(gè)整數(shù),表示了執(zhí)行該方法后服務(wù)器返回的狀態(tài)碼,該狀態(tài)碼能表示出該方法執(zhí)行是否成功、需要認(rèn)證或者頁(yè)面發(fā)生了跳轉(zhuǎn)(默認(rèn)狀態(tài)下GetMethod的實(shí)例是自動(dòng)處理跳轉(zhuǎn)的)等。
            //設(shè)置成了默認(rèn)的恢復(fù)策略,在發(fā)生異常時(shí)候?qū)⒆詣?dòng)重試3次,在這里你也可以設(shè)置成自定義的恢復(fù)策略
                            getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                            new DefaultHttpMethodRetryHandler());
                            //執(zhí)行g(shù)etMethod
                            int statusCode = client.executeMethod(getMethod);
                            if (statusCode != HttpStatus.SC_OK) {
                            System.err.println("Method failed: " + getMethod.getStatusLine());
                            }
                            

          • 在返回的狀態(tài)碼正確后,即可取得內(nèi)容。取得目標(biāo)地址的內(nèi)容有三種方法:第一種,getResponseBody,該方法返回的是目標(biāo)的二進(jìn)制的byte流;第二種,getResponseBodyAsString,這個(gè)方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據(jù)系統(tǒng)默認(rèn)的編碼方式,所以返回的String值可能編碼類型有誤,在本文的"字符編碼"部分中將對(duì)此做詳細(xì)介紹;第三種,getResponseBodyAsStream,這個(gè)方法對(duì)于目標(biāo)地址中有大量數(shù)據(jù)需要傳輸是最佳的。在這里我們使用了最簡(jiǎn)單的getResponseBody方法。
            byte[] responseBody = method.getResponseBody();
                            

          • 釋放連接。無(wú)論執(zhí)行方法是否成功,都必須釋放連接。
            method.releaseConnection();
                            

          • 處理內(nèi)容。在這一步中根據(jù)你的需要處理內(nèi)容,在例子中只是簡(jiǎn)單的將內(nèi)容打印到控制臺(tái)。
            System.out.println(new String(responseBody));
                            

          下面是程序的完整代碼,這些代碼也可在附件中的test.GetSample中找到。


          package test;
                      import java.io.IOException;
                      import org.apache.commons.httpclient.*;
                      import org.apache.commons.httpclient.methods.GetMethod;
                      import org.apache.commons.httpclient.params.HttpMethodParams;
                      public class GetSample{
                      public static void main(String[] args) {
                      //構(gòu)造HttpClient的實(shí)例
                      HttpClient httpClient = new HttpClient();
                      //創(chuàng)建GET方法的實(shí)例
                      GetMethod getMethod = new GetMethod("http://www.ibm.com");
                      //使用系統(tǒng)提供的默認(rèn)的恢復(fù)策略
                      getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                      new DefaultHttpMethodRetryHandler());
                      try {
                      //執(zhí)行g(shù)etMethod
                      int statusCode = httpClient.executeMethod(getMethod);
                      if (statusCode != HttpStatus.SC_OK) {
                      System.err.println("Method failed: "
                      + getMethod.getStatusLine());
                      }
                      //讀取內(nèi)容
                      byte[] responseBody = getMethod.getResponseBody();
                      //處理內(nèi)容
                      System.out.println(new String(responseBody));
                      } catch (HttpException e) {
                      //發(fā)生致命的異常,可能是協(xié)議不對(duì)或者返回的內(nèi)容有問題
                      System.out.println("Please check your provided http address!");
                      e.printStackTrace();
                      } catch (IOException e) {
                      //發(fā)生網(wǎng)絡(luò)異常
                      e.printStackTrace();
                      } finally {
                      //釋放連接
                      getMethod.releaseConnection();
                      }
                      }
                      }
                      

          POST方法

          根據(jù)RFC2616,對(duì)POST的解釋如下:POST方法用來向目的服務(wù)器發(fā)出請(qǐng)求,要求它接受被附在請(qǐng)求后的實(shí)體,并把它當(dāng)作請(qǐng)求隊(duì)列(Request-Line)中請(qǐng)求URI所指定資源的附加新子項(xiàng)。POST被設(shè)計(jì)成用統(tǒng)一的方法實(shí)現(xiàn)下列功能:

          • 對(duì)現(xiàn)有資源的注釋(Annotation of existing resources)
          • 向電子公告欄、新聞組,郵件列表或類似討論組發(fā)送消息
          • 提交數(shù)據(jù)塊,如將表單的結(jié)果提交給數(shù)據(jù)處理過程
          • 通過附加操作來擴(kuò)展數(shù)據(jù)庫(kù)

          調(diào)用HttpClient中的PostMethod與GetMethod類似,除了設(shè)置PostMethod的實(shí)例與GetMethod有些不同之外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不同的地方,并以登錄清華大學(xué)BBS為例子進(jìn)行說明。

          • 構(gòu)造PostMethod之前的步驟都相同,與GetMethod一樣,構(gòu)造PostMethod也需要一個(gè)URI參數(shù),在本例中,登錄的地址是http://www.newsmth.net/bbslogin2.php。在創(chuàng)建了PostMethod的實(shí)例之后,需要給method實(shí)例填充表單的值,在BBS的登錄表單中需要有兩個(gè)域,第一個(gè)是用戶名(域名叫id),第二個(gè)是密碼(域名叫passwd)。表單中的域用類NameValuePair來表示,該類的構(gòu)造函數(shù)第一個(gè)參數(shù)是域名,第二參數(shù)是該域的值;將表單所有的值設(shè)置到PostMethod中用方法setRequestBody。另外由于BBS登錄成功后會(huì)轉(zhuǎn)向另外一個(gè)頁(yè)面,但是HttpClient對(duì)于要求接受后繼服務(wù)的請(qǐng)求,比如POST和PUT,不支持自動(dòng)轉(zhuǎn)發(fā),因此需要自己對(duì)頁(yè)面轉(zhuǎn)向做處理。具體的頁(yè)面轉(zhuǎn)向處理請(qǐng)參見下面的"自動(dòng)轉(zhuǎn)向"部分。代碼如下:
            String url = "http://www.newsmth.net/bbslogin2.php";
                            PostMethod postMethod = new PostMethod(url);
                            // 填入各個(gè)表單域的值
                            NameValuePair[] data = { new NameValuePair("id", "youUserName"),
                            new NameValuePair("passwd", "yourPwd") };
                            // 將表單的值放入postMethod中
                            postMethod.setRequestBody(data);
                            // 執(zhí)行postMethod
                            int statusCode = httpClient.executeMethod(postMethod);
                            // HttpClient對(duì)于要求接受后繼服務(wù)的請(qǐng)求,象POST和PUT等不能自動(dòng)處理轉(zhuǎn)發(fā)
                            // 301或者302
                            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||
                            statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                            // 從頭中取出轉(zhuǎn)向的地址
                            Header locationHeader = postMethod.getResponseHeader("location");
                            String location = null;
                            if (locationHeader != null) {
                            location = locationHeader.getValue();
                            System.out.println("The page was redirected to:" + location);
                            } else {
                            System.err.println("Location field value is null.");
                            }
                            return;
                            }
                            

          posted on 2008-01-29 14:55 agun 閱讀(488) 評(píng)論(0)  編輯  收藏 所屬分類: java web

          主站蜘蛛池模板: 临夏县| 汝城县| 旌德县| 潮安县| 温宿县| 上犹县| 望都县| 揭东县| 肃宁县| 宁波市| 昭通市| 盖州市| 张家界市| 漠河县| 内江市| 平山县| 霍山县| 渑池县| 双城市| 濮阳县| 郴州市| 桐柏县| 盱眙县| 肥西县| 茶陵县| 黄梅县| 汕头市| 嵊泗县| 车险| 吴忠市| 德昌县| 山东省| 鄂尔多斯市| 静乐县| 沐川县| 杭锦旗| 县级市| 花莲县| 民县| 淳化县| 岱山县|