client.executeMethod(post);
System.out.println(post.getStatusLine().toString());
post.releaseConnection();
//
檢查是否重定向
int
statuscode
=
post.getStatusCode();
if
((statuscode
==
HttpStatus.SC_MOVED_TEMPORARILY)
||
(statuscode
==
HttpStatus.SC_MOVED_PERMANENTLY)
||
(statuscode
==
HttpStatus.SC_SEE_OTHER)
||
(statuscode
==
HttpStatus.SC_TEMPORARY_REDIRECT))
{//讀取新的URL地址
Header header = post.getResponseHeader("location");
if (header != null) {
String newuri = header.getValue();
if ((newuri == null) || (newuri.equals("")))
newuri = "/";
GetMethod redirect = new GetMethod(newuri);
client.executeMethod(redirect);
System.out.println("Redirect:"+ redirect.getStatusLine().toString());
redirect.releaseConnection();
} else {
System.out.println("Invalid redirect");
} 咱們能夠自行編寫兩個JSP頁面,其中一個頁面用response.sendRedirect方法重定向到另一個頁面用來測試上面的例子。
4. 模擬輸入用戶名和口令進行登陸
本 小節應該說是HTTP客戶端編程中最常遇見的問題,不少網站的內容都只是對註冊用戶可見的,這種狀況下就必需要求使用正確的用戶名和口令登陸成功後,方可 瀏覽到想要的頁面。由於HTTP協議是無狀態的,也就是鏈接的有效期只限於當前請求,請求內容結束後鏈接就關閉了。在這種狀況下爲了保存用戶的登陸信息必 須使用到Cookie機制。以JSP/Servlet爲例,當瀏覽器請求一個JSP或者是Servlet的頁面時,應用服務器會返回一個參數,名爲 jsessionid(因不一樣應用服務器而異),值是一個較長的惟一字符串的Cookie,這個字符串值也就是當前訪問該站點的會話標識。瀏覽器在每訪問 該站點的其餘頁面時候都要帶上jsessionid這樣的Cookie信息,應用服務器根據讀取這個會話標識來獲取對應的會話信息。
對於 須要用戶登陸的網站,通常在用戶登陸成功後會將用戶資料保存在服務器的會話中,這樣當訪問到其餘的頁面時候,應用服務器根據瀏覽器送上的Cookie中讀 取當前請求對應的會話標識以得到對應的會話信息,而後就能夠判斷用戶資料是否存在於會話信息中,若是存在則容許訪問頁面,不然跳轉到登陸頁面中要求用戶輸 入賬號和口令進行登陸。這就是通常使用JSP開發網站在處理用戶登陸的比較通用的方法。
這樣一來,對於HTTP的客戶端來說,若是要訪問 一個受保護的頁面時就必須模擬瀏覽器所作的工做,首先就是請求登陸頁面,而後讀取Cookie值;再次請求登陸頁面並加入登陸頁所需的每一個參數;最後就是 請求最終所需的頁面。固然在除第一次請求外其餘的請求都須要附帶上Cookie信息以便服務器能判斷當前請求是否已經經過驗證。說了這麼多,但是若是你使 用httpclient的話,你甚至連一行代碼都無需增長,你只須要先傳遞登陸信息執行登陸過程,而後直接訪問想要的頁面,跟訪問一個普通的頁面沒有任何 區別,由於類HttpClient已經幫你作了全部該作的事情了,太棒了!下面的例子實現了這樣一個訪問的過程。
/*
* Created on 2003-12-7 by Liudong
*/
package
http.demo;
import
org.apache.commons.httpclient.
*
;
import
org.apache.commons.httpclient.cookie.
*
;
import
org.apache.commons.httpclient.methods.
*
;
/**
* 用來演示登陸表單的示例
* @author Liudong
*/
public
class
FormLoginDemo
{
static final String LOGON_SITE = "localhost";
static final int LOGON_PORT = 8080;
public static void main(String[] args) throws Exception{
HttpClient client = new HttpClient();
client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);
//模擬登陸頁面login.jsp->main.jsp
PostMethod post = new PostMethod("/main.jsp");
NameValuePair name = new NameValuePair("name", "ld");
NameValuePair pass = new NameValuePair("password", "ld");
post.setRequestBody(new NameValuePair[]{name,pass});
int status = client.executeMethod(post);
System.out.println(post.getResponseBodyAsString());
post.releaseConnection();
//查看cookie信息
CookieSpec cookiespec = CookiePolicy.getDefaultSpec();
Cookie[] cookies = cookiespec.match(LOGON_SITE, LOGON_PORT, "/", false, client.getState().getCookies());
if (cookies.length == 0) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.length; i++) {
System.out.println(cookies[i].toString());
}
}
//訪問所需的頁面main2.jsp
GetMethod get = new GetMethod("/main2.jsp");
client.executeMethod(get);
System.out.println(get.getResponseBodyAsString());
get.releaseConnection();
}
}
5. 提交XML格式參數
提交XML格式的參數很簡單,僅僅是一個提交時候的ContentType問題,下面的例子演示從文件文件中讀取XML信息並提交給服務器的過程,該過程能夠用來測試Web服務。
import
java.io.File;
import
java.io.FileInputStream;
import
org.apache.commons.httpclient.HttpClient;
import
org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import
org.apache.commons.httpclient.methods.PostMethod;
/**
* 用來演示提交XML格式數據的例子
*/
public
class
PostXMLClient
{
public static void main(String[] args) throws Exception {
File input = new File(「test.xml」);
PostMethod post = new PostMethod(「http://localhost:8080/httpclient/xml.jsp」);
// 設置請求的內容直接從文件中讀取
post.setRequestBody(new FileInputStream(input));
if (input.length() < Integer.MAX_VALUE)
post.setRequestContentLength(input.length());
else
post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);
// 指定請求內容的類型
post.setRequestHeader("Content-type", "text/xml; charset=GBK");
HttpClient httpclient = new HttpClient();
int result = httpclient.executeMethod(post);
System.out.println("Response status code: " + result);
System.out.println("Response body: ");
System.out.println(post.getResponseBodyAsString());
post.releaseConnection();
}
}
6. 經過HTTP上傳文件
httpclient使用了單獨的一個HttpMethod子類來處理文件的上傳,這個類就是MultipartPostMethod,該類已經封裝了文件上傳的細節,咱們要作的僅僅是告訴它咱們要上傳文件的全路徑便可,下面的代碼片斷演示如何使用這個類。
MultipartPostMethod filePost
=
new
MultipartPostMethod(targetURL);
filePost.addParameter(
"
fileName
"
, targetFilePath);
HttpClient client
=
new
HttpClient();
//
因爲要上傳的文件可能比較大,所以在此設置最大的鏈接超時時間
client.getHttpConnectionManager().getParams().setConnectionTimeout(
5000
);
int
status
=
client.executeMethod(filePost);
上面代碼中,targetFilePath即爲要上傳的文件所在的路徑。
7. 訪問啓用認證的頁面
我 們常常會碰到這樣的頁面,當訪問它的時候會彈出一個瀏覽器的對話框要求輸入用戶名和密碼後方可,這種用戶認證的方式不一樣於咱們在前面介紹的基於表單的用戶 身份驗證。這是HTTP的認證策略,httpclient支持三種認證方式包括:基本、摘要以及NTLM認證。其中基本認證最簡單、通用但也最不安全;摘 要認證是在HTTP 1.1中加入的認證方式,而NTLM則是微軟公司定義的而不是通用的規範,最新版本的NTLM是比摘要認證還要安全的一種方式。
下面例子是從httpclient的CVS服務器中下載的,它簡單演示如何訪問一個認證保護的頁面:
import
org.apache.commons.httpclient.HttpClient;
import
org.apache.commons.httpclient.UsernamePasswordCredentials;
import
org.apache.commons.httpclient.methods.GetMethod;
public
class
BasicAuthenticationExample
{
public BasicAuthenticationExample() {
}
public static void main(String[] args) throws Exception {
HttpClient client = new HttpClient();
client.getState().setCredentials(
"www.verisign.com",
"realm",
new UsernamePasswordCredentials("username", "password")
);
GetMethod get = new GetMethod("https://www.verisign.com/products/index.html";);
get.setDoAuthentication( true );
int status = client.executeMethod( get );
System.out.println(status+""+ get.getResponseBodyAsString());
get.releaseConnection();
}
}
8. 多線程模式下使用httpclient
多 線程同時訪問httpclient,例如同時從一個站點上下載多個文件。對於同一個HttpConnection同一個時間只能有一個線程訪問,爲了保證 多線程工做環境下不產生衝突,httpclient使用了一個多線程鏈接管理器的類: MultiThreadedHttpConnectionManager,要使用這個類很簡單,只須要在構造HttpClient實例的時候傳入便可,代 碼以下:
MultiThreadedHttpConnectionManager connectionManager
=
new
MultiThreadedHttpConnectionManager();
HttpClient client
=
new
HttpClient(connectionManager);