本文介紹如何利用apache的HttpClient包進行http操作,包括get操作和post操作。
一、下面的代碼是對HttpClient包的封裝,以便於更好的編寫應用代碼。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import org.apache.commons.httpclient.Cookie; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.util.URIUtil; import org.apache.commons.lang.StringUtils; public class MyHttpClient { private HttpClient httpClient; private String cookies; public MyHttpClient(String ip) { this(ip, 80); } public MyHttpClient(String ip, int port) { httpClient = new HttpClient(); httpClient.getHostConfiguration().setHost(ip, port, "http"); httpClient.getParams().setCookiePolicy( CookiePolicy.BROWSER_COMPATIBILITY); } public String getCookies(){ return cookies; } public void setCookies(String cookies){ this.cookies = cookies; } public String doGet(String url) throws IOException{ return doGet(url,null); } public String doGet(String url, String paras) throws IOException { GetMethod method = new GetMethod(url); if (StringUtils.isNotBlank(paras)) { method.setQueryString(URIUtil.encodeQuery(paras)); } return sendRequest(method); } public String doPost(String url) throws IOException{ return doPost(url,new HashMap<String,String>()); } public String doPost(String url, String paras) throws IOException { Map<String,String> paraMap = new HashMap<String,String>(); String[] values = paras.split("&"); for(String value:values){ String[] item = value.split("="); if(item.length==2){ paraMap.put(item[0].trim(), item[1].trim()); } } return doPost(url,paraMap); } public String doPost(String url, Map<String,String> paras) throws IOException{ int index=0; NameValuePair[] data = new NameValuePair[paras.size()]; for(Map.Entry<String,String> entry:paras.entrySet()){ data[index++] = new NameValuePair(entry.getKey(),entry.getValue()); } return doPost(url,data); } private String doPost(String url, NameValuePair[] data) throws IOException{ PostMethod method = new PostMethod(url); method.setRequestBody(data); method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8"); return sendRequest(method); } private String sendRequest(HttpMethod method) throws IOException{ StringBuffer response = new StringBuffer(); try { method.setRequestHeader("Cookie", cookies); httpClient.executeMethod(method); if (method.getStatusCode() == HttpStatus.SC_OK) { response.append(getResponseBody(method)); }else if(method.getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY){ //302 重定向 response.append(getResponseHeader(method)); }else { System.out.println("response statuscode : " + method.getStatusCode()); throw new IllegalStateException("response statuscode : " + method.getStatusCode()); } fetchCookies(); }finally { method.releaseConnection(); } return response.toString(); } private void fetchCookies(){ Cookie[] values = httpClient.getState().getCookies(); StringBuffer cookieBuffer = new StringBuffer(); for (Cookie c : values) { cookieBuffer.append(c.toString()).append(";"); } cookies = cookieBuffer.toString(); } private String getResponseBody(HttpMethod method) throws IOException, IOException { StringBuffer response = new StringBuffer(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader( method.getResponseBodyAsStream(), "UTF-8")); String line; while ((line = reader.readLine()) != null) { response.append(line).append( System.getProperty("line.separator")); } }finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } return response.toString(); } private String getResponseHeader(HttpMethod method){ StringBuffer response = new StringBuffer(); Header[] headers = method.getResponseHeaders(); for(Header header:headers){ String line = header.getName()+" : "+header.getValue(); response.append(line); response.append(System.getProperty("line.separator")); } return response.toString(); } }
說明:上面代碼中doGet方法中的 語句 String encodeQuery = URIUtil.encodeQuery(paras);
存在一點問題,當url部門有特殊字符,如空格、+ 號等,這些字符需要被編碼。
這時需要換成 String encodeQuery = URIUtil.encodePath(paras); 語句,即用encodePath方法替代encodeQuery方法。
二、下面來進行實際的使用舉例
1、簡單的get操作
下面的代碼完成對一個url的get操作。我們封裝了兩個doGet操作,一個是帶參數的,一個是不帶參數的。待參數的參數格式如 name1=value1&name2=value2
MyHttpClient httpClient = new MyHttpClient("xxxx"); //xxxx是web服務器的地址
String result = httpClient.doGet(url); //url是請求的url地址
System.out.println(result);
2、簡單的post操作
下面的代碼完成對一個url的post操作.
MyHttpClient httpClient = new MyHttpClient("localhost"); Map<String,String> paras = new HashMap<String,String>(); paras.put("para1", "value1"); paras.put("para2", "value2"); String result = httpClient.doPost(url,paras); System.out.println(result);
3、有重定向的get操作
如果發起的一個get操作,被服務器重定向到一個新的url。這時我們封裝的doGet操作返回的是新的url(重定向后的)對應的信息。
4、有重定向的post操作
如果發起的一個post操作,被服務器重定向到一個新的url。我們封裝的doPost操作,與doGet操作返回的結果不同,doPost是返回重定向頭信息,而不是新的url的信息。如返回如下的信息,其中Location對應的值login就是重定向的url
Server : Apache-Coyote/1.1
Set-Cookie : JSESSIONID=8115A882086E7F27809FDF24213F82F5; Path=/boot/; HttpOnly
Set-Cookie :Expires=Thu, 01-Jan-1970 00:00:10 GMT
Location : login
Content-Length : 0
Date : Sat, 09 Jan 2016 07:41:21 GMT
5、需要登錄的請求
有的web服務器有鑒權功能,當發起一個請求時,如果在該請求之前還沒有登錄,會自動重定向到登錄頁面,登錄成功后才會跳轉到想要請求的頁面。
這時代碼應該這樣寫:
MyHttpClient httpClient = new MyHttpClient("localhost"); //下面是登錄請求 httpClient.doPost(loginUrl,"username=xxx&password=yyy"); //因為前面已經登錄,下面的url將不會發生重定向。而是返回該url對應頁面的本身信息。 String result = httpClient.doGet(url); System.out.println(result);
6、與cookie有關的請求
有的web應用中,用到了cookie。所謂的cookie,就是希望瀏覽器操作關閉后,會在瀏覽器本地客戶端機器上記錄下一些信息。當下次打開瀏覽器,操作相關的頁面后,這些信息能被帶到服務器。我們封裝的這個功能對此也支持。具體通過例子說明:
MyHttpClient httpClient = new MyHttpClient("localhost"); //下面的操作,會產生cookie httpClient.doPost(url,paras); //獲取本次會話產生的cookie String cookies = httpClient.getCookies(); //開啟一個新的會話 MyHttpClient otherHttpClient = new MyHttpClient("localhost"); //將上次會話的cookie設置到本次會話中,以便於cookie能帶到服務器 otherHttpClient.setCookies(cookies); //這次請求就會上個會話產生的cookie帶到服務器 String result = otherHttpClient.doGet(otherUrl); System.out.println(result);
三、小結
我們封裝的這個httpclient類,可以很方便的完成http請求的一些基本操作。並且對有鑒權控制、cookie功能的網站也能較好的滿足。