HttpClient程序包是一個實現了 HTTP協議的客戶端編程工具包,要想熟練的掌握它,必須熟悉 HTTP協議。對於HTTP協議來說,無非就是用戶請求數據,服務器端響應用戶請求,並將內容結果返回給用戶。HTTP1.1由以下幾種請求組成:GET,HEAD, POST, PUT, DELETE, TRACE ,OPTIONS,因此對應到HttpClient程序包中分別用HttpGet,HttpHead, HttpPost, HttpPut, HttpDelete, HttpTrace, HttpOptions
這幾個類來創建請求。所有的這些類均實現了HttpUriRequest接口,故可以作爲execute的執行參數使用。
l HTTP請求
當然在所有請求中最常用的還是GET與POST兩種請求,創建請求的方式如下:
HttpUriRequest request = newHttpPost("http://localhost/index.html");
HttpUriRequest request = newHttpGet(“http://127.0.0.1:8080/index.html”);
HTTP請求格式告訴我們,有兩種方式可以爲request提供參數:request-line方式與request-body方式。
Ø request-line方式是指在請求行上通過URI直接提供參數。
(1)可以在生成request對象時提供帶參數的URI,如:
HttpUriRequest request = newHttpGet("http://localhost/index.html?param1=value1¶m2=value2");
(2)HttpClient程序包還提供了URIUtils工具類,可以通過它生成帶參數的URI,如:
URI uri =URIUtils.createURI("http", "localhost", -1,"/index.html",
"param1=value1¶m2=value2", null);
HttpUriRequest request = newHttpGet(uri);
System.out.println(request.getURI());
上例的實例結果如下:
http://localhost/index.html?param1=value1¶m2=value2
(3)需要注意的是,如果參數中含有中文,需將參數進行URLEncoding處理,如:
String param ="param1=" + URLEncoder.encode("中國", "UTF-8") +"¶m2=value2";
URI uri =URIUtils.createURI("http", "localhost", 8080,"/sshsky/index.html",param, null);
System.out.println(uri);
上例的實例結果如下:
http://localhost/index.html?param1=%E4%B8%AD%E5%9B%BD¶m2=value2
(4)對於參數的URLEncoding處理,HttpClient程序包爲我們準備了另一個工具類:URLEncodedUtils。通過它,我們可以直觀的(但是比較複雜)生成URI,如:
01 |
List
params = newArrayList(); |
03 |
params.add(newBasicNameValuePair( "param1" , "中國" )); |
05 |
params.add(newBasicNameValuePair( "param2" , "value2" )); |
07 |
String
param =URLEncodedUtils.format(params, "UTF-8" ); |
09 |
URI
uri =URIUtils.createURI( "http" , "localhost" , 8080 , "/sshsky/index.html" ,param, null ); |
11 |
System.out.println(uri); |
上例的實例結果如下:
http://localhost/index.html?param1=%E4%B8%AD%E5%9B%BD¶m2=value2
Ø request-body方式是指在請求的request-body中提供參數
與 request-line方式不同,request-body方式是在request-body中提供參數,此方式只能用於進行POST請求。在HttpClient程序包中有兩個類可以完成此項工作,它們分別是UrlEncodedFormEntity類與MultipartEntity類。這 兩個類均實現了HttpEntity接口。
(1)UrlEncodedFormEntity類,故名思意該類主要用於form表單提交。通過該類創建的對象可以模擬傳統的HTML表單傳送POST請求中的參數。如下面的表單:
1 |
< formaction = "http://localhost/index.html" method = "POST" > |
3 |
< inputtype = "text" name = "param1" value = "中國" /> |
5 |
< inputtype = "text" name = "param2" value = "value2" /> |
7 |
< inupttype = "submit" value = "submit" /> |
即可以通過下面的代碼實現:
01 |
List
formParams = newArrayList(); |
03 |
formParams.add(newBasicNameValuePair( "param1" , "中國" )); |
05 |
formParams.add(newBasicNameValuePair( "param2" , "value2" )); |
07 |
HttpEntity
entity = newUrlEncodedFormEntity(formParams, "UTF-8" ); |
09 |
HttpPost
request = newHttpPost(“http: |
11 |
request.setEntity(entity); |
當然,如果想查看HTTP數據格式,可以通過HttpEntity對象的各種方法取得。如:
01 |
List
formParams = newArrayList(); |
03 |
formParams.add(newBasicNameValuePair( "param1" , "中國" )); |
05 |
formParams.add(newBasicNameValuePair( "param2" , "value2" )); |
07 |
UrlEncodedFormEntity
entity = new UrlEncodedFormEntity(formParams, "UTF-8" ); |
09 |
System.out.println(entity.getContentType()); |
11 |
System.out.println(entity.getContentLength()); |
13 |
System.out.println(EntityUtils.getContentCharSet(entity)); |
15 |
System.out.println(EntityUtils.toString(entity)); |
上例的實例結果如下:
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
39
UTF-8
param1=%E4%B8%AD%E5%9B%BD¶m2=value2
(2)除了傳統的application/x-www-form-urlencoded表單,還有另一個經常用到的是上傳文件用的表單,這種表單的類型爲 multipart/form-data。在HttpClient程序擴展包(HttpMime)中專門有一個類與之對應,那就是MultipartEntity類。此類同樣實現了HttpEntity接口。如下面的表單:
01 |
< formaction = "http://localhost/index.html" method = "POST" |
03 |
enctype = "multipart/form-data" > |
05 |
< inputtype = "text" name = "param1" value = "中國" /> |
07 |
< inputtype = "text" name = "param2" value = "value2" /> |
09 |
< inputtype = "file" name = "param3" /> |
11 |
< inupttype = "submit" value = "submit" /> |
可以用下面的代碼實現:
01 |
MultipartEntity
entity = newMultipartEntity(); |
03 |
entity.addPart( "param1" , new StringBody( "中國" ,
Charset.forName( "UTF-8" ))); |
05 |
entity.addPart( "param2" , new StringBody( "value2" ,
Charset.forName( "UTF-8" ))); |
07 |
entity.addPart( "param3" , new FileBody( new File( "C:\\1.txt" ))); |
09 |
HttpPost
request = newHttpPost(“http: |
11 |
request.setEntity(entity); |
l HTTP響應
HttpClient 程序包對於HTTP響應的處理較請求來說簡單多了,其過程同樣使用了HttpEntity接口。我們可以從HttpEntity對象中取出數據流(InputStream),該數據流就是服務器返回的響應數據。需要注意的是,HttpClient程序包不負責 解析數據流中的內容。如:
01 |
HttpUriRequest
request = ...; |
03 |
HttpResponse
response =httpClient.execute(request); |
07 |
HttpEntity
entity =response.getEntity(); |
11 |
System.out.println(entity.getContentType()); |
13 |
System.out.println(entity.getContentLength()); |
15 |
System.out.println(EntityUtils.getContentCharSet(entity)); |
19 |
InputStream
stream =entity.getContent(); |
或者採用如下的接口方式httpClient.execute(request,new ResponseHandler<T> response)進行調用,它的返回值直接對應的即爲用戶自己想獲取的數據的類型及值。
具體實例解析,通過下述方法,即可獲取到指定url的頁面內容。
01 |
public static String
executeStringByGet(String url, final Charset
charset) { |
05 |
HttpClient
client = new DefaultHttpClient(); |
07 |
HttpGet
get = new HttpGet(url); |
13 |
result
= client.execute(get, new ResponseHandler<String>()
{ |
17 |
public String
handleResponse(HttpResponse response) throws ClientProtocolException,
IOException { |
19 |
HttpEntity
entity = response.getEntity(); |
23 |
if (response.getStatusLine().getStatusCode()
== HttpStatus.SC_OK) { |
25 |
return new String(EntityUtils.toByteArray(entity),
charset.getValue()); |
37 |
} catch (Exception
e) { |
HttpClient接口的詳細使用:
001 |
package com.wow.common.test; |
005 |
import java.io.IOException; |
007 |
import java.util.regex.Matcher; |
009 |
import java.util.regex.Pattern; |
013 |
import org.apache.http.Header; |
015 |
import org.apache.http.HttpEntity; |
017 |
import org.apache.http.HttpResponse; |
019 |
import org.apache.http.HttpStatus; |
021 |
import org.apache.http.client.ClientProtocolException; |
023 |
import org.apache.http.client.HttpClient; |
025 |
import org.apache.http.client.methods.HttpGet; |
027 |
import org.apache.http.impl.client.DefaultHttpClient; |
029 |
import org.apache.http.util.EntityUtils; |
035 |
*
類HttpClientTest.java的實現描述:TODO 類實現描述 |
037 |
*
@author zheng.zhaoz 2012-2-9 下午07:33:18 |
041 |
public class HttpClientTest
{ |
045 |
public static void main(String[]
args) { |
047 |
HttpClient
httpClient = new DefaultHttpClient(); |
051 |
HttpGet
httpGet = new HttpGet( "http://www.cnblogs.com/loveyakamoz/archive/2011/07/21/2113252.html" ); |
057 |
httpGet.setHeader( "Accept" , "Accept
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" ); |
059 |
httpGet.setHeader( "Accept-Charset" , "GB2312,utf-8;q=0.7,*;q=0.7" ); |
061 |
httpGet.setHeader( "Accept-Encoding" , "gzip,
deflate" ); |
063 |
httpGet.setHeader( "Accept-Language" , "zh-cn,zh;q=0.5" ); |
065 |
httpGet.setHeader( "Connection" , "keep-alive" ); |
067 |
httpGet.setHeader( "Cookie" , "__utma=226521935.73826752.1323672782.1325068020.1328770420.6;" ); |
069 |
httpGet.setHeader( "Host" , "www.cnblogs.com" ); |
071 |
httpGet.setHeader( "refer" , "http://www.baidu.com/s?tn=monline_5_dg&bs=httpclient4+MultiThreadedHttpConnectionManager" ); |
073 |
httpGet.setHeader( "User-Agent" , "Mozilla/5.0
(Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2" ); |
075 |
System.out.println( "Accept-Charset:
" +
httpGet.getFirstHeader( "Accept-Charset" )); |
077 |
System.out.println( "Execute
request: " +
httpGet.getURI()); |
081 |
HttpResponse
response = null ; |
085 |
response
= httpClient.execute(httpGet); |
087 |
} catch (ClientProtocolException
e) { |
091 |
} catch (IOException
e) { |
101 |
if (response
!= null )
{ |
103 |
Header
headers[] = response.getAllHeaders(); |
107 |
while (i
< headers.length) { |
109 |
System.out.println(headers[i].getName()
+ ":
" +
headers[i].getValue()); |
115 |
if (response.getStatusLine().getStatusCode()
== HttpStatus.SC_OK) { |
119 |
HttpEntity
entity = response.getEntity(); |
123 |
byte []
bytes = EntityUtils.toByteArray(entity); |
129 |
charSet
= EntityUtils.getContentCharSet(entity); |
131 |
System.out.println( "In
header: " +
charSet); |
137 |
String
regEx= "(?=<meta).*?(?<=charset=[\\'|\\\"]?)([[a-z]|[A-Z]|[0-9]|-]*)" ; |
139 |
Pattern
p=Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); |
141 |
Matcher
m=p.matcher( new String(bytes)); |
143 |
boolean result
= m.find(); |
145 |
if (m.groupCount()
== 1 )
{ |
147 |
charSet
= m.group( 1 ); |
157 |
System.out.println( "Last
get: " +
charSet); |
161 |
System.out.println( "Encoding
string is: " + new String(bytes,
charSet)); |
163 |
} catch (IOException
e) { |
175 |
httpClient.getConnectionManager().shutdown(); |