170314、工具:apache httpClient多線程並發情況下安全實用及工具類分享


簡單用法介紹:介紹來源網絡

建立連接:在HttpClient中使用多線程的一個主要原因是可以一次執行多個方法。在執行期間,每一個方法都使用一個HttpConnection實例。由於在同一時間多個連接只能安全地用於單一線程和方法和有限的資源,我們就必須確保連接分配給正確的方法。而MultiThreadedHttpConnectionManager完全可以代替我們完成這一項工作,這樣我們就不必去考慮多線程帶來安全的問題。

MultiThreadedHttpConnectionManager connectionManager =new MultiThreadedHttpConnectionManager();

HttpClient client = new HttpClient(connectionManager);

以上代碼中的HttpClient就在多線程中執行多個方法了。當我們再次調用httpClient.executeMethod()方法時,就會去Connection Manager中去請求HttpConneciton的實例,這樣就避免了線程安全問題,因為HttpClient已經幫我們做了。

釋放連接:Connection Management比較重要的是當連接不再使用時,一定要手動釋放。這樣做的原因是HttpClient不能夠確定哪個方法不被使用,哪個方法還在使用。這是因為Response body不是由HttpClient來自動讀取其數據的,而是由使用HttpClient的應用程序來完成的。當讀取Response的數據是時,必須使用此方法的連接。這樣,在Response的數據在讀取前,HttpClient是沒有釋放連接的。所有這就要求在讀取完Response的數據后,應用程序及時的使用releaseConnection()方法來釋放連接。特別注意,無論執行的方法或是否也不例外被拋出。對於每一個HttpClient.executeMethod方法必須有一個method.releaseConnection ( )來釋放連接。

重用HttpClient實例:一般說來,建議一個通訊組件,甚至說一個應用軟件就始終維持一個HttpClient對象實例存在。但是如果你的應用很稀罕才用到它,而且還不允許這么一個實例一直存在,那么,這里強烈建議,一定要顯式地shut down 它的MultiThreadedHttpConnectionManager 。這樣做是確保連接池里的Connection得到釋放。 

HttpMethod並發執行:如果應用程序邏輯允許並發執行多個HTTP請求,(例如對多個服務器的多個並發請求,或對同一個服務器代表不同用戶身份的多個請求) ,應用程序可以為每一個HTTP session開啟一個專門的線程,這樣的設計自然將帶來顯著的性能提升。 而當使用一個線程安全的連接管理器MultiThreadedHttpConnectionManager 時,HttpClient能保證線程安全。這樣,多個線程可以共享這么一個線程安全的HttpClient實例。請注意,應用程序的每個各自執行的線程必須使用各自的HttpMethod實例;並且可配置各自的HttpState實例和/或HostConfiguration實例(代表一個特定的會話狀態和主機配置)。這個共享的HttpClient和其標配的MultiThreadedHttpConnectionManager將為各線程帶來最高的性能。

使用流來發送和接收數據:HttpClient同時支持Stream和String/byte[]兩種方式來發送和接受數據,但是由於String/byte[]的方式會造成內存中有一份數據的拷貝或緩存,那么當請求或應答報文比較大,或者在高並發的應用中,使用String/byte[]就會造成額外的內存開銷,所以使用流的方式來傳輸數據是更好的選擇。

HttpClient的三種超時說明

/* 從連接池中取連接的超時時間 */

ConnManagerParams.setTimeout(params, 1000);

/* 連接超時 */

HttpConnectionParams.setConnectionTimeout(params, 2000);

/* 請求超時 */

HttpConnectionParams.setSoTimeout(params, 4000);

第一行設置ConnectionPoolTimeout:這定義了從ConnectionManager管理的連接池中取出連接的超時時間,此處設置為1秒。

第二行設置ConnectionTimeout:  這定義了通過網絡與服務器建立連接的超時時間。Httpclient包中通過一個異步線程去創建與服務器的socket連接,這就是該socket連接的超時時間,此處設置為2秒。

第三行設置SocketTimeout:    這定義了Socket讀數據的超時時間,即從服務器獲取響應數據需要等待的時間,此處設置為4秒。

以上3種超時分別會拋出ConnectionPoolTimeoutException,ConnectionTimeoutException與SocketTimeoutException。

工具類:jar包commons-httpclient-3.1.jar

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.util.Map;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;

import org.apache.commons.httpclient.HostConfiguration;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.HttpException;

import org.apache.commons.httpclient.HttpMethod;

import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;

import org.apache.commons.httpclient.NameValuePair;

import org.apache.commons.httpclient.methods.GetMethod;

import org.apache.commons.httpclient.methods.PostMethod;

import org.apache.commons.httpclient.methods.RequestEntity;

import org.apache.commons.httpclient.methods.StringRequestEntity;

import org.apache.commons.httpclient.params.HttpClientParams;

import org.apache.commons.httpclient.params.HttpConnectionManagerParams;

import org.apache.commons.httpclient.params.HttpMethodParams;

import org.apache.commons.httpclient.protocol.Protocol;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

public class HttpClientTemplate {

private static Logger logger = LoggerFactory.getLogger(HttpClientTemplate.class);

    private MultiThreadedHttpConnectionManager multiThreadConnManager;

    private HttpClient client;

    public HttpClientTemplate() {

        HttpConnectionManagerParams params = new HttpConnectionManagerParams();

        params.setParameter(HttpMethodParams.RETRY_HANDLER,

            new DefaultHttpMethodRetryHandler());

        params.setMaxTotalConnections(10);

        params.setDefaultMaxConnectionsPerHost(5);

        params.setSoTimeout(10 * 1000);

        params.setConnectionTimeout(10 * 1000);

        multiThreadConnManager = new MultiThreadedHttpConnectionManager();

        multiThreadConnManager.setParams(params);

    }

    private HttpClient getHttpClient() {

        if (client == null)

            synchronized (this) {

                client = new HttpClient(multiThreadConnManager);

                HttpClientParams params = new HttpClientParams();

                params.setContentCharset("UTF-8");

                client.setParams(params);

            }

        return client;

    }

//生成get方法

    private GetMethod genMethod(String baseUrl, String queryString) {

        GetMethod get = new GetMethod(baseUrl);

        get.setQueryString(queryString);

        return get;

    }

//生成get方法

    private GetMethod genMethod(String baseUrl, Map<String, Object> paramMap) {

        GetMethod get = new GetMethod(baseUrl);

        HttpMethodParams params = new HttpMethodParams();

        params.setContentCharset("UTF-8");

        get.setParams(params);

        if (paramMap != null) {

            NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];

            int i = 0;

            for (Map.Entry<String, Object> entry: paramMap.entrySet()) {

                nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()

                    .toString());

            }

            get.setQueryString(nvp);

        }

        return get;

    }

    public String execute(String baseUrl, Map<String, Object> paramMap) {

     if(logger.isDebugEnabled()) {

     logger.debug("[sending] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));

     }

     try {

        GetMethod method = genMethod(baseUrl, paramMap);

        String result = execute(method);

        if(logger.isDebugEnabled()) {

     logger.debug("[receiving] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));

     }

        return result;

     }

     catch(Exception e) {

     logger.error("[http exception] url={}, param={}", baseUrl, JSON.toJSONString(paramMap), e);

     return null;

     }   

    }

    //json格式請求

    public String excuteJson(String baseUrl, Map<String, Object> paramMap)

     throws HttpException, IOException

    {

     if(logger.isDebugEnabled()) {

     logger.debug("[sending json] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));

     }

      JSONObject json = new JSONObject();

      json.putAll(paramMap);

      PostMethod method = new PostMethod(baseUrl);

      RequestEntity requestEntity = new StringRequestEntity(json.toString(), "application/json", "UTF-8");

      method.setRequestEntity(requestEntity);

      String result = execute(method);

      if(logger.isDebugEnabled()) {

      logger.debug("[receiving json] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));

      }

      return result;

    }

//post請求

    public String executePost(String baseUrl, Map<String, Object> paramMap){

     try {

     if(logger.isDebugEnabled()) {

     logger.debug("[sending post] url={}, param={}", baseUrl, JSON.toJSONString(paramMap));

     }

        PostMethod method = new PostMethod(baseUrl);

        HttpMethodParams params = new HttpMethodParams();

        params.setContentCharset("UTF-8");

        method.setParams(params);

        if (paramMap != null) {

            NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];

            int i = 0;

            for (Map.Entry<String, Object> entry: paramMap.entrySet()) {

                nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()

                    .toString());

            }

            method.addParameters(nvp);

        }

        String result = execute(method);

        if(logger.isDebugEnabled()) {

      logger.debug("[receiving post] result ={}, url={}, param={}",result, baseUrl, JSON.toJSONString(paramMap));

      }

      return result;

     }

     catch(Exception e) {

     logger.error("[http post exception] url={}, param={}", baseUrl, JSON.toJSONString(paramMap), e);

     return null;

     }

    }

 

    public String executePost(String baseUrl, Map<String, Object> paramMap,

        Map<String, Object> headerParams) throws HttpException, IOException {

     if(logger.isDebugEnabled()) {

     logger.debug("[sending head] url={}, param={}, head={}", baseUrl, 

     JSON.toJSONString(paramMap), JSON.toJSONString(headerParams));

     }

        PostMethod method = new PostMethod(baseUrl);

        HttpMethodParams params = new HttpMethodParams();

        params.setContentCharset("UTF-8");

        method.setParams(params);

        if (paramMap != null) {

            NameValuePair[] nvp = new NameValuePair[paramMap.values().size()];

            int i = 0;

            for (Map.Entry<String, Object> entry: paramMap.entrySet()) {

                nvp[i++] = new NameValuePair(entry.getKey(), entry.getValue()

                    .toString());

            }

            method.addParameters(nvp);

        }

 

        if (headerParams != null) {

            // HttpMethodParams mparams = new HttpMethodParams();

            // mparams.setContentCharset("UTF-8");

            // mparams.setVirtualHost(headerParams.get("hostUrl").toString());

            // method.setParams(mparams);

            method.getParams().setVirtualHost(

                headerParams.get("hostUrl").toString());

        }

        String result = execute(method, headerParams);

        if(logger.isDebugEnabled()) {

      logger.debug("[receiving head] result ={}, url={}, param={}, head={}",result, baseUrl, 

      JSON.toJSONString(paramMap), JSON.toJSONString(headerParams));

      }

      return result;

    }

 

    public String execute(String url) throws HttpException, IOException {

        GetMethod method = new GetMethod(url);

        return execute(method);

    }

 

    public String execute(String baseUrl, String queryString)

        throws HttpException, IOException {

        GetMethod method = genMethod(baseUrl, queryString);

        return execute(method);

    }

 

    private String execute(HttpMethod method) throws HttpException, IOException {

        try {

            int statusCode = getHttpClient().executeMethod(method);

            if (200 != statusCode) {

                throw new HttpException("status code: " + statusCode);

            } else {

               // return method.getResponseBodyAsString();

             InputStream resStream = method.getResponseBodyAsStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(

                    resStream, "UTF-8"));

                StringBuffer resBuffer = new StringBuffer();

                String resTemp = "";

                while ((resTemp = br.readLine()) != null) {

                    resBuffer.append(resTemp);

                }

                return resBuffer.toString();

            }

        } finally {

            if (null != method)

                method.releaseConnection();

        }

    }

 

    private String execute(HttpMethod method, Map<String, Object> headerParams)

        throws HttpException, IOException {

        try {

            HttpClient httpClient = getHttpClient();

            if (headerParams != null) {

                HostConfiguration hf = new HostConfiguration();

                if (headerParams.get("hostUrl") != null) {

                    hf.setHost(headerParams.get("hostUrl").toString(), 80,

                        Protocol.getProtocol("http"));

                }

                httpClient.setHostConfiguration(hf);

            }

            int statusCode = httpClient.executeMethod(method);

            if (200 != statusCode) {

                throw new HttpException("status code: " + statusCode);

            } else {

                // return method.getResponseBodyAsString();

                InputStream resStream = method.getResponseBodyAsStream();

                BufferedReader br = new BufferedReader(new InputStreamReader(

                    resStream, "UTF-8"));

                StringBuffer resBuffer = new StringBuffer();

                String resTemp = "";

                while ((resTemp = br.readLine()) != null) {

                    resBuffer.append(resTemp);

                }

                return resBuffer.toString();

            }

        } finally {

            if (null != method)

                method.releaseConnection();

        }

    }

    public static class Factory {

        private static HttpClientTemplate instance = new HttpClientTemplate();

 

        public static HttpClientTemplate getClient() {

            return Factory.instance;

        }

    }

public static void main(String[] args) {

     HttpClientTemplate clientTemplate = HttpClientTemplate.Factory.instance;

     Map<String, Object> paramMap = new LinkedHashMap<>();

     String result = clientTemplate.executePost("", paramMap);

}

}

 


免責聲明!

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



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