zoukankan      html  css  js  c++  java
  • 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);

    }

    }

  • 相关阅读:
    netty源码学习
    大话数据结构读书笔记
    java编程思想读书笔记
    spring依赖注入源码分析和mongodb自带连接本地mongodb服务逻辑分析
    spring的xml的property和constructor-arg的解析
    junit测试用例加载spring配置文件
    (大二下)软件需求分析阅读笔记01
    课后作业——需求分析
    2018年春季个人阅读计划
    软件需求与分析——大二下需会知识点
  • 原文地址:https://www.cnblogs.com/zrbfree/p/6708785.html
Copyright © 2011-2022 走看看