国产成人毛片视频|星空传媒久草视频|欧美激情草久视频|久久久久女女|久操超碰在线播放|亚洲强奸一区二区|五月天丁香社区在线|色婷婷成人丁香网|午夜欧美6666|纯肉无码91视频

HttpClient 簡介

HttpClient 簡介HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 H

HttpClient 簡介

HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。本文首先介紹

HTTPClient ,然后根據(jù)作者實際工作經(jīng)驗給出了一些常見問題的解決方法。HTTP 協(xié)議可能是現(xiàn)在 Internet 上使用得最多、最重要的協(xié)議了,越來越多的 Java 應用程序需要直接通過 HTTP 協(xié)議來訪問網(wǎng)絡資源。雖然在 JDK 的 java.net 包中已經(jīng)提供了訪問 HTTP 協(xié)議的基本功能,但是對于大部分應用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。HttpClient 已經(jīng)應用在很多的項目中,比如 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient 。現(xiàn)在HttpClient 最新版本為 HttpClient 4.0-beta2

2.HttpClient 功能介紹

以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。

(1)實現(xiàn)了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)

(2)支持自動轉向

(3)支持 HTTPS 協(xié)議

(4)支持代理服務器等

3.HttpClient 基本功能的使用

(1) GET方法

使用 HttpClient 需要以下 6 個步驟:

,

1. 創(chuàng)建 HttpClient 的實例

2. 創(chuàng)建某種連接方法的實例,在這里是 GetMethod 。在 GetMethod 的構造函數(shù)中傳入待連接的地址

3. 調(diào)用第一步中創(chuàng)建好的實例的 execute 方法來執(zhí)行第二步中創(chuàng)建好的 method 實例

4. 讀 response

5. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接

6. 對得到后的內(nèi)容進行處理

根據(jù)以上步驟,我們來編寫用GET 方法來取得某網(wǎng)頁內(nèi)容的代碼。 大部分情況下 HttpClient 默認的構造函數(shù)已經(jīng)足夠使用。 HttpClient httpClient = new HttpClient();

創(chuàng)建GET 方法的實例。在GET 方法的構造函數(shù)中傳入待連接的地址即可。用GetMethod 將會自動處理轉發(fā)過程,如果想要把自動處理轉發(fā)過程去掉 的話,可以調(diào)用方法setFollowRedirects(false)。

GetMethod getMethod = new GetMethod(".....");

調(diào)用實例httpClient 的executeMethod 方法來執(zhí)行getMethod 。由于是執(zhí)行在網(wǎng)絡上的程序,在運行 executeMethod 方法的時候,需要處理兩個異常,分別是HttpException 和IOException 。引起第一種異常的原因主要可能是 在構造getMethod 的時候傳入的協(xié)議不對,比如不小心將"http" 寫成"htp" ,或者服務器端返回的內(nèi)容不正常等,并且該異常發(fā)生是不可恢復 的;第二種異常一般是由于網(wǎng)絡原因引起的異常,對于這種異常 (IOException ),HttpClient 會根據(jù)你指定的恢復策略自動試著重新執(zhí)行executeMethod 方法。HttpClient 的恢復 策略可以自定義(通過實現(xiàn)接口HttpMethodRetryHandler 來實現(xiàn))。通過httpClient 的方法setParameter 設置你實 現(xiàn)的恢復策略,本文中使用的是系統(tǒng)提供的默認恢復策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod 返回值是一個整數(shù),表示 了執(zhí)行該方法后服務

,

器返回的狀態(tài)碼,該狀態(tài)碼能表示出該方法執(zhí)行是否成功、需要認證或者頁面發(fā)生了跳轉(默認狀態(tài)下GetMethod 的實例是自動處理跳 轉的)等。 //設置成了默認的恢復策略,在發(fā)生異常時候將自動重試3次,在這里你也可以設置成自定義的恢復策略

getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,

new DefaultHttpMethodRetryHandler());

//執(zhí)行getMethod

int statusCode = client.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) {

System.err.println("Method failed: "

getMethod.getStatusLine());

}

在返回的狀態(tài)碼正確后,即可取得內(nèi)容。取得目標地址的內(nèi)容有三種方法:第一種,getResponseBody ,該方法返回的是目標的二進制的 byte 流;第二種,getResponseBodyAsString ,這個方法返回的是String 類型,值得注意的是該方法返回的String 的編碼 是根據(jù)系統(tǒng)默認的編碼方式,所以返回的String 值可能編碼類型有誤,在本文的" 字符編碼" 部分中將對此做詳細介紹;第三 種,

getResponseBodyAsStream ,這個方法對于目標地址中有大量數(shù)據(jù)需要傳輸是最佳的。在這里我們使用了最簡單的 getResponseBody 方法。 byte[] responseBody = method.getResponseBody(); 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接。

method.releaseConnection();

處理內(nèi)容。在這一步中根據(jù)你的需要處理內(nèi)容,在例子中只是簡單的將內(nè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) {

//構造HttpClient 的實例

HttpClient httpClient = new HttpClient();

//創(chuàng)建GET 方法的實例

GetMethod getMethod = new GetMethod("...");

//使用系統(tǒng)提供的默認的恢復策略

getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,

new DefaultHttpMethodRetryHandler());

try {

//執(zhí)行getMethod

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é)議不對或者返回的內(nèi)容有問題

System.out.println("Please check your provided http address!"); e.printStackTrace();

} catch (IOException e) {

//發(fā)生網(wǎng)絡異常

e.printStackTrace();

} finally {

//釋放連接

getMethod.releaseConnection();

}

}

}

(2)POST 方法

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

對現(xiàn)有資源的注釋(Annotation of existing resources) 向電子公告欄、新聞組,郵件列表或類似討論組發(fā)送消息 提交數(shù)據(jù)塊,如將表單的結果提交給數(shù)據(jù)處理過程

通過附加操作來擴展數(shù)據(jù)庫

調(diào)用HttpClient 中的PostMethod 與GetMethod 類似,除了設置

,

PostMethod 的實例與GetMethod 有些不同之 外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod 相同的步驟,只說明與上面不同的地方,并以登錄清華大學BBS 為例子進行說明。

構造PostMethod 之前的步驟都相同,與GetMethod 一樣,構造PostMethod 也需要一個URI 參數(shù)。在創(chuàng)建了 PostMethod 的實例之后,需要給method 實例填充表單的值,在BBS 的登錄表單中需要有兩個域,第一個是用戶名(域名叫id ),第二個是密碼 (域名叫

passwd )。表單中的域用類NameValuePair 來表示,該類的構造函數(shù)第一個參數(shù)是域名,第二參數(shù)是該域的值;將表單所有的值設置到

PostMethod 中用方法setRequestBody 。另外由于BBS 登錄成功后會轉向另外一個頁面,但是HttpClient 對于要求接受后繼服 務的請求,比如POST 和PUT ,不支持自動轉發(fā),因此需要自己對頁面轉向做處理。具體的頁面轉向處理請參見下面的" 自動轉向" 部分。代碼如下: String url = "....";

PostMethod postMethod = new PostMethod(url);

// 填入各個表單域的值

NameValuePair[] data = { new NameValuePair("id",

"youUserName"),

new NameValuePair("passwd", "yourPwd") };

// 將表單的值放入postMethod 中

postMethod.setRequestBody(data);

// 執(zhí)行postMethod

int statusCode = httpClient.executeMethod(postMethod); // HttpClient對于要求接受后繼服務的請求,象POST 和PUT 等不能自動處理轉發(fā)

// 301或者302

if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||

,

statusCode == HttpStatus.SC_MOVED_TEMPORARILY) { // 從頭中取出轉向的地址

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;

}

[編輯本段]4 使用HttpClient 過程中常見的一些問題 下面介紹在使用HttpClient 過程中常見的一些問題。

字符編碼

某目標頁的編碼可能出現(xiàn)在兩個地方,第一個地方是服務器返回的http 頭中,另外一個地方是得到的html/xml頁面中。

在http 頭的Content-Type 字段可能會包含字符編碼信息。例如可能返回的頭會包含這樣子的信息:Content-Type: text/html;

charset=UTF-8。這個頭信息表明該頁的編碼是UTF-8,但是服務器返回的頭信息未必與內(nèi)容能匹配上。比如對于一些雙字節(jié)語言國家,可能服務 器返回的編碼類型是UTF-8,但真正的內(nèi)容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁面的編碼信息;但是如果服務器返回的編碼不是UTF- 8,而是具體的一些編碼,比如gb2312等,那服務器返回的可能是正確的編碼信息。通過method 對象的getResponseCharSet()方 法就可以得到http 頭中的編碼信息。

,

對于象xml 或者html 這樣的文件,允許作者在頁面中直接指定編碼類型。比如在html 中會有

content="text/html; charset=gb2312"/>這樣的標簽;或者在xml 中會有這樣的標簽,在這些情況下,可能與http 頭中返回的編碼信息沖突,需要用戶自己判斷到底那種編碼類型應該 是真正的編碼。

自動轉向

根據(jù)RFC2616中對自動轉向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當返回的是301,則表示請求的資源已經(jīng)被移到一個固定的新地方,任何向該地址發(fā)起請求都會被轉到新的地址上。302表示暫時 的轉向,比如在服務器端的servlet 程序調(diào)用了sendRedirect 方法,則在客戶端就會得到一個302的代碼,這時服務器返回的頭信息中 location 的值就是sendRedirect 轉向的目標地址。

HttpClient 支持自動轉向處理,但是象POST 和PUT 方式這種要求接受后繼服務的請求方式,暫時不支持自動轉向,因此如果碰到POST 方式 提交后返回的是301或者302的話需要自己處理。就像剛才在

POSTMethod 中舉的例子:如果想進入登錄BBS 后的頁面,必須重新發(fā)起登錄的請求, 請求的地址可以在頭字段location 中得到。不過需要注意的是,有時候location 返回的可能是相對路徑,因此需要對location 返回的值做 一些處理才可以發(fā)起向新地址的請求。

另外除了在頭中包含的信息可能使頁面發(fā)生重定向外,在頁面中也有可能會發(fā)生頁面的重定向。引起頁面自動轉發(fā)的標簽是:。如果你想在程序中也處理這種情況的話得自己分析頁面來實現(xiàn)轉向。需要注意的是,在上面那個標簽中url 的值也可以是一個相對 地址,如果是這樣的話,需要對它做一些處理后才可以轉發(fā)。

,

處理HTTPS 協(xié)議

HttpClient 提供了對SSL 的支持,在使用SSL 之前必須安裝JSSE 。在Sun 提供的1.4以后的版本中,JSSE 已經(jīng)集成到JDK 中,如 果你使用的是JDK1.4以前的版本則必須安裝JSSE 。JSSE 不同的廠家有不同的實現(xiàn)。下面介紹怎么使用HttpClient 來打開Https 連接。 這里有兩種方法可以打開https 連接,第一種就是得到服務器頒發(fā)的證書,然后導入到本地的keystore 中;另外一種辦法就是通過擴展 HttpClient 的類來實現(xiàn)自動接受證書。

方法1,取得證書,并導入本地的keystore :

安裝JSSE (如果你使用的JDK 版本是1.4或者1.4以上就可以跳過這一步)。本文以IBM 的JSSE 為例子說明。先到IBM 網(wǎng)站上下載JSSE 的安裝包。然后解 壓開之后將ibmjsse.jar 包拷貝到

home>libext目錄下。

取得并且導入證書。證書可以通過IE 來獲得:

1. 用IE 打開需要連接的https 網(wǎng)址,會彈出如下對話框:

2. 單擊"View Certificate",在彈出的對話框中選擇"Details" ,然后再單擊"Copy to File",根據(jù)提供的向導生成待訪問網(wǎng)頁的證書文件

3. 向導第一步,歡迎界面,直接單擊"Next" ,

4. 向導第二步,選擇導出的文件格式,默認,單擊"Next" ,

5. 向導第三步,輸入導出的文件名,輸入后,單擊"Next" ,

6. 向導第四步,單擊"Finish" ,完成向導

7. 最后彈出一個對話框,顯示導出成功

用keytool 工具把剛才導出的證書倒入本地keystore 。Keytool 命令在bin下,打開命令行窗口,并到

home>libsecurity目錄下,運行下面的命令:

keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer

,

其中參數(shù)alias 后跟的值是當前證書在keystore 中的唯一標識符,但是大小寫不區(qū)分;參數(shù)file 后跟的是剛才通過IE 導出的證書所在的路徑和文件名;如果你想刪除剛才導入到keystore 的證書,可以用命令: keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1

寫程序訪問https 地址。如果想測試是否能連上https ,只需要稍改一下GetSample 例子,把請求的目標變成一個https 地址。 GetMethod getMethod = new GetMethod("your url"); 運行該程序可能出現(xiàn)的問題:

1. 拋出異常java.net.SocketException: Algorithm SSL not

available 。出現(xiàn)這個異??赡苁且驗闆]有加JSSEProvider ,如果用的是IBM 的JSSE Provider,在程序中加入這樣的一行:

if(Security.getProvider("com.ibm.jsse.IBMJSSEProvider") == null)

Security.addProvider(new IBMJSSEProvider());

或者也可以打開libsecurityjava.security,在行 security.provider.1=sun.security.provider.Sun

security.provider.2=com.ibm.crypto.provider.IBMJCE

后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider

2. 拋出異常java.net.SocketException: SSL implementation not available 。出現(xiàn)這個異??赡苁悄銢]有把ibmjsse.jar 拷貝到libext目錄下。

3. 拋出異常javax.net.ssl.SSLHandshakeException: unknown certificate 。出現(xiàn)這個異常表明你的JSSE 應該已經(jīng)安裝正確,但是可能因為你沒有把證書導入到當前運行JRE 的keystore 中,請按照前 面介紹的步驟來導入你的證書。

方法2,擴展HttpClient 類實現(xiàn)自動接受證書

標簽: