Java網絡編程:利用apache的HttpClient包進行http操作


本文介紹如何利用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功能的網站也能較好的滿足。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM