JavaHTTPClient入門.doc_第1頁
JavaHTTPClient入門.doc_第2頁
JavaHTTPClient入門.doc_第3頁
JavaHTTPClient入門.doc_第4頁
JavaHTTPClient入門.doc_第5頁
已閱讀5頁,還剩3頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

HTTPClient入門HttpClient 是 Apache Jakarta Common 下的子項目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。本文首先介紹 HTTPClient,然后根據作者實際工作經驗給出了一些常見問題的解決方法。HttpClient簡介HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程序需要直接通過 HTTP 協議來訪問網絡資源。雖然在 JDK 的 包中已經提供了訪問 HTTP 協議的基本功能,但是對于大部分應用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持 HTTP 協議的客戶端編程工具包,并且它支持 HTTP 協議最新的版本和建議。HttpClient 已經應用在很多的項目中,比如 Apache Jakarta 上很著名的另外兩個開源項目 Cactus 和 HTMLUnit 都使用了 HttpClient,更多使用 HttpClient 的應用可以參見/jakarta-httpclient/HttpClientPowered。HttpClient 項目非常活躍,使用的人還是非常多的。目前 HttpClient 版本是在 2005.10.11 發布的 3.0 RC4 。HttpClient 功能介紹以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細的功能可以參見 HttpClient 的主頁。實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等) 支持自動轉向 支持 HTTPS 協議 支持代理服務器等 下面將逐一介紹怎樣使用這些功能。首先,我們必須安裝好 HttpClient。HttpClient 可以在/commons/httpclient/downloads.html下載HttpClient 用到了 Apache Jakarta common 下的子項目 logging,你可以從這個地址/site/downloads/downloads_commons-logging.cgi下載到 common logging,從下載后的壓縮包中取出 commons-logging.jar 加到 CLASSPATH 中HttpClient 用到了 Apache Jakarta common 下的子項目 codec,你可以從這個地址/site/downloads/downloads_commons-codec.cgi 下載到最新的 common codec,從下載后的壓縮包中取出 commons-codec-1.x.jar 加到 CLASSPATH 中HttpClient 基本功能的使用GET 方法使用 HttpClient 需要以下 6 個步驟: 1. 創建 HttpClient 的實例2. 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址3. 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例4. 讀 response5. 釋放連接。無論執行方法是否成功,都必須釋放連接6. 對得到后的內容進行處理根據以上步驟,我們來編寫用GET方法來取得某網頁內容的代碼。大部分情況下 HttpClient 默認的構造函數已經足夠使用。 HttpClient httpClient = new HttpClient();創建GET方法的實例。在GET方法的構造函數中傳入待連接的地址即可。用GetMethod將會自動處理轉發過程,如果想要把自動處理轉發過程去掉的話,可以調用方法setFollowRedirects(false)。 GetMethod getMethod = new GetMethod(/);調用實例httpClient的 executeMethod方法來執行getMethod。由于是執行在網絡上的程序,在運行executeMethod方法的時候,需要處理兩個異常, 分別是HttpException和IOException。引起第一種異常的原因主要可能是在構造getMethod的時候傳入的協議不對,比如不小心 將http寫成htp,或者服務器端返回的內容不正常等,并且該異常發生是不可恢復的;第二種異常一般是由于網絡原因引起的異常,對于這種異常 (IOException),HttpClient會根據你指定的恢復策略自動試著重新執行executeMethod方法。HttpClient的恢復 策略可以自定義(通過實現接口HttpMethodRetryHandler來實現)。通過httpClient的方法setParameter設置你實 現的恢復策略,本文中使用的是系統提供的默認恢復策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod返回值是一個整數,表示 了執行該方法后服務器返回的狀態碼,該狀態碼能表示出該方法執行是否成功、需要認證或者頁面發生了跳轉(默認狀態下GetMethod的實例是自動處理跳 轉的)等。 /設置成了默認的恢復策略,在發生異常時候將自動重試3次,在這里你也可以設置成自定義的恢復策略getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(); /執行getMethodint statusCode = client.executeMethod(getMethod);if (statusCode != HttpStatus.SC_OK) System.err.println(Method failed: + getMethod.getStatusLine();在返回的狀態碼正確后,即可取得內容。取得目標地址的內容有三種方法:第一種,getResponseBody,該方法返回的是目標的二進制的byte 流;第二種,getResponseBodyAsString,這個方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據系 統默認的編碼方式,所以返回的String值可能編碼類型有誤,在本文的字符編碼部分中將對此做詳細介紹;第三種, getResponseBodyAsStream,這個方法對于目標地址中有大量數據需要傳輸是最佳的。在這里我們使用了最簡單的 getResponseBody方法。 byte responseBody = method.getResponseBody();釋放連接。無論執行方法是否成功,都必須釋放連接。 method.releaseConnection();處理內容。在這一步中根據你的需要處理內容,在例子中只是簡單的將內容打印到控制臺。 System.out.println(new String(responseBody);下面是程序的完整代碼,這些代碼也可在附件中的test.GetSample中找到。package test;import java.io.IOException;import mons.httpclient.*;import mons.httpclient.methods.GetMethod;import mons.httpclient.params.HttpMethodParams;public class GetSamplepublic static void main(String args) /構造HttpClient的實例 HttpClient httpClient = new HttpClient(); /創建GET方法的實例 GetMethod getMethod = new GetMethod(); /使用系統提供的默認的恢復策略 getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(); try /執行getMethod int statusCode = httpClient.executeMethod(getMethod); if (statusCode != HttpStatus.SC_OK) System.err.println(Method failed: + getMethod.getStatusLine(); /讀取內容 byte responseBody = getMethod.getResponseBody(); /處理內容 System.out.println(new String(responseBody); catch (HttpException e) /發生致命的異常,可能是協議不對或者返回的內容有問題 System.out.println(Please check your provided http address!); e.printStackTrace(); catch (IOException e) /發生網絡異常 e.printStackTrace(); finally /釋放連接 getMethod.releaseConnection(); POST方法根據RFC2616,對POST的解釋如下:POST方法用來向目的服務器發出請求,要求它接受被附在請求后的實體,并把它當作請求隊列(Request-Line)中請求URI所指定資源的附加新子項。POST被設計成用統一的方法實現下列功能:對現有資源的注釋(Annotation of existing resources)向電子公告欄、新聞組,郵件列表或類似討論組發送消息提交數據塊,如將表單的結果提交給數據處理過程通過附加操作來擴展數據庫調 用HttpClient中的PostMethod與GetMethod類似,除了設置PostMethod的實例與GetMethod有些不同之外,剩下 的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不同的地方,并以登錄清華大學BBS為例子進行說明。構 造PostMethod之前的步驟都相同,與GetMethod一樣,構造PostMethod也需要一個URI參數,在本例中,登錄的地址是http: //bbslogin2.php。在創建了PostMethod的實例之后,需要給method實例填充表單的值,在 BBS的登錄表單中需要有兩個域,第一個是用戶名(域名叫id),第二個是密碼(域名叫passwd)。表單中的域用類NameValuePair來表 示,該類的構造函數第一個參數是域名,第二參數是該域的值;將表單所有的值設置到PostMethod中用方法setRequestBody。另外由于 BBS登錄成功后會轉向另外一個頁面,但是HttpClient對于要求接受后繼服務的請求,比如POST和PUT,不支持自動轉發,因此需要自己對頁面 轉向做處理。具體的頁面轉向處理請參見下面的自動轉向部分。代碼如下: String url = /bbslogin2.php;PostMethod postMethod = new PostMethod(url);/ 填入各個表單域的值NameValuePair data = new NameValuePair(id, youUserName), new NameValuePair(passwd, yourPwd) ;/ 將表單的值放入postMethod中postMethod.setRequestBody(data);/ 執行postMethodint statusCode = httpClient.executeMethod(postMethod);/ HttpClient對于要求接受后繼服務的請求,象POST和PUT等不能自動處理轉發/ 301或者302if (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;使用HttpClient過程中常見的一些問題下面介紹在使用HttpClient過程中常見的一些問題。字符編碼某目標頁的編碼可能出現在兩個地方,第一個地方是服務器返回的http頭中,另外一個地方是得到的html/xml頁面中。在http 頭的Content-Type字段可能會包含字符編碼信息。例如可能返回的頭會包含這樣子的信息:Content-Type: text/html; charset=UTF-8。這個頭信息表明該頁的編碼是UTF-8,但是服務器返回的頭信息未必與內容能匹配上。比如對于一些雙字節語言國家,可能服務 器返回的編碼類型是UTF-8,但真正的內容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁面的編碼信息;但是如果服務器返回的編碼不是UTF- 8,而是具體的一些編碼,比如gb2312等,那服務器返回的可能是正確的編碼信息。通過method對象的getResponseCharSet()方 法就可以得到http頭中的編碼信息。對于象xml或者html這樣的文件,允許作者在頁面中直接指定編碼類型。比如在 html中會有這樣的標簽;或者在xml中會有這樣的標簽,在這些情況下,可能與http頭中返回的編碼信息沖突,需要用戶自己判斷到底那種編碼類型應該 是真正的編碼。自動轉向根 據RFC2616中對自動轉向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當返回的是301,則表示請求的資源已經被移到一個固定的新地方,任何向該地址發起請求都會被轉到新的地址上。302表示暫時 的轉向,比如在服務器端的servlet程序調用了sendRedirect方法,則在客戶端就會得到一個302的代碼,這時服務器返回的頭信息中 location的值就是sendRedirect轉向的目標地址。HttpClient支持自動轉向處理,但是象POST和 PUT方式這種要求接受后繼服務的請求方式,暫時不支持自動轉向,因此如果碰到POST方式提交后返回的是301或者302的話需要自己處理。就像剛才在 POSTMethod中舉的例子:如果想進入登錄BBS后的頁面,必須重新發起登錄的請求,請求的地址可以在頭字段location中得到。不過需要注意 的是,有時候location返回的可能是相對路徑,因此需要對location返回的值做一些處理才可以發起向新地址的請求。另 外除了在頭中包含的信息可能使頁面發生重定向外,在頁面中也有可能會發生頁面的重定向。引起頁面自動轉發的標簽是:。如果你想在程序中也處理這種情況的話得自己分析頁面來實現轉向。需要注意的是,在上面那個標簽中url的值也可以是一個相對地址,如果是這樣的話,需要對它做一些處理后才可以轉發。處理HTTPS協議HttpClient 提供了對SSL的支持,在使用SSL之前必須安裝JSSE。在Sun提供的1.4以后的版本中,JSSE已經集成到JDK中,如果你使用的是JDK1.4 以前的版本則必須安裝JSSE。JSSE不同的廠家有不同的實現。下面介紹怎么使用HttpClient來打開Https連接。這里有兩種方法可以打開 https連接,第一種就是得到服務器頒發的證書,然后導入到本地的keystore中;另外一種辦法就是通過擴展HttpClient的類來實現自動接受證書。方法1,取得證書,并導入本地的keystore:安裝JSSE (如果你使用的JDK版本是1.4或者1.4以上就可以跳過這一步)。本文以IBM的JSSE為例子說明。先到IBM網站上下載JSSE的安裝包。然后解 壓開之后將ibmjsse.jar包拷貝到libext目錄下。取得并且導入證書。證書可以通過IE來獲得: 1 用IE打開需要連接的https網址,會彈出如下對話框:2 單擊View Certificate,在彈出的對話框中選擇Details,然后再單擊Copy to File,根據提供的向導生成待訪問網頁的證書文件3 向導第一步,歡迎界面,直接單擊Next,4 向導第二步,選擇導出的文件格式,默認,單擊Next,5 向導第三步,輸入導出的文件名,輸入后,單擊Next,6 向導第四步,單擊Finish,完成向導7 最后彈出一個對話框,顯示導出成功用keytool工具把剛才導出的證書倒入本地keystore。Keytool命令在bin下,打開命令行窗口,并到libsecurity目錄下,運行下面的命令:keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer其中參數alias后跟的值是當前證書在keystore中的唯一標識符,但是大小寫不區分;參數file后跟的是剛才通過IE導出的證書所在的路徑和文件名;如果你想刪除剛才導入到keystore的證書,可以用命令:keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1寫程序訪問https地址。如果想測試是否能連上https,只需要稍改一下GetSample例子,把請求的目標變成一個https地址。 GetMethod getMethod = new GetMethod(); 運行該程序可能出現的問題:1. 拋出異常.SocketException: Algorithm SSL not available。出現這個異常可能是因為沒有加JSSEProvider,如果用的是IBM的JSSE Provider,在程序中加入這樣的一行:if(Security.getProvider(com.ibm.jsse.IBMJSSEProvider) = null)Security.addProvider(new IBMJSSEProvider();或者也可以打開libsecurityjava.security,在行vider.1=vider.Svider.2=vider.IBMJCE后面加入vider.3=com.ibm.jsse.IBMJSSEProvider2. 拋出異常.SocketException: SSL implementation not available。出現這個異常可能是你沒有把ibmjsse.jar拷貝到libext目錄下。3. 拋出異常.ssl.SSLHandshakeException: unknown certificate。出現這個異常表明你的JSSE應該已經安裝正確,但是可能因為你沒有把證書導入到當前運行JRE的keystore中,請按照前 面介紹的步驟來導入你的證書。方法,擴展HttpClient類實現自動接受證書因為這種方法自動接收所有證書,因此存在一定的安全問題,所以在使用這種方法前請仔細考慮您的系統的安全需求。具體的步驟如下:提 供一個自定義的socket factory(test.MySecureProtocolSocketFactory)。這個自定義的類必須實現接口 tocol.SecureProtocolSocketFactory,在實現接口 的類中調用自定義的X509TrustManager(test.MyX509TrustManager),這兩個類可以在隨本文帶的附件中得到創建一個tocol.Protocol的實例,指定協議名稱和默認的端口號 Protocol myhttps = new Protocol(https, new MySecureProtocolSocketFactory (), 443);注冊剛才創建的https協議對象 Protocol.registerProtocol(https , myhttps);然后按照普通編程方式打開https的目標地址,代碼請參見test.NoCertificationHttpsGetSample處理代理服務器HttpClient中使用代理服務器非常簡單,調用HttpClient中setProxy方法就可以,方法的第一個參數是代理服務器地址,第二個參數是端口號。另外HttpClient也支持SOCKS代理。httpClient.getHostConfiguration().setProxy(hostName,port);回頁首結論從上面的介紹中,可以知道HttpClient對http協議支持非常

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論