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);
}
}
170314、工具:apache httpClient多线程并发情况下安全实用及工具类分享的更多相关文章
- 喜提JDK的BUG一枚!多线程的情况下请谨慎使用这个类的stream遍历。
你好呀,我是歪歪. 前段时间在 RocketMQ 的 ISSUE 里面冲浪的时候,看到一个 pr,虽说是在 RocketMQ 的地盘上发现的,但是这个玩意吧,其实和 RocketMQ 没有任何关系. ...
- 多线程并发情况下 重复insert问题
代码逻辑: if(数据不存在){ insert(); } 线程启动后,发现数据库表中有相同的记录 解决方案 synchronized同步代码块即加同步锁,synchronized同步代码块的功能: 当 ...
- PHP通过加锁实现并发情况下抢码实现
需求:抢码功能 要求: 1.特定时间段才开放抢码: 2.每个时间段放开的码是有限的: 3.每个码不允许重复: 实现: 1.在不考虑并发的情况下实现: function get_code($len){ ...
- PHP通过加锁实现并发情况下抢码功能
本文基于php语言使用加锁实现并发情况下抢码功能,特定时间段开放抢码并不允许开放的码重复: 需求:抢码功能 要求: 1.特定时间段才开放抢码: 2.每个时间段放开的码是有限的: 3.每个码不允许重复: ...
- Jackson高并发情况下,产生阻塞
情况:在高并发情况下,查看线程栈信息,有大量的线程BLOCKED. 从线程栈得知,线程栈中出现了阻塞,锁在了com.fasterxml.jackson.databind.ser.SerializerC ...
- Linux的虚拟内存管理-如何分配和释放内存,以提高服务器在高并发情况下的性能,从而降低了系统的负载
Linux的虚拟内存管理有几个关键概念: Linux 虚拟地址空间如何分布?malloc和free是如何分配和释放内存?如何查看堆内内存的碎片情况?既然堆内内存brk和sbrk不能直接释放,为什么不全 ...
- c# redis 利用锁(StackExchange.Redis LockTake)来保证数据在高并发情况下的正确性
之前有写过一篇介绍c#操作redis的文章 http://www.cnblogs.com/axel10/p/8459434.html ,这篇文章中的案例使用了StringIncrement来实现了高并 ...
- 面试官问:HashMap在并发情况下为什么造成死循环?一脸懵
这个问题是在面试时常问的几个问题,一般在问这个问题之前会问Hashmap和HashTable的区别?面试者一般会回答:hashtable是线程安全的,hashmap是线程不安全的. 那么面试官就会紧接 ...
- 关于WCF服务在高并发情况下报目标积极拒绝的异常处理
最近弄了个wcf的监控服务,偶尔监控到目标服务会报一个目标积极拒绝的错误.一开始以为服务停止了,上服务器检查目标服务好好的活着.于是开始查原因. 一般来说目标积极拒绝(TCP 10061)的异常主要是 ...
随机推荐
- RPC服务框架dubbo(二):dubbo支持的注册中心
Zookeeper 1 优点:支持网络集群 2 缺点:稳定性受限于Zookeeper zookeeper的详细信息看这里:https://www.cnblogs.com/shamo89/tag/Zoo ...
- Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception process Vob7
Atitit.js javascript异常处理机制与java异常的转换 多重catc hDWR 环境 .js exception processVob7 1. 1. javascript异常处理机制 ...
- Leetcode[81]-Search for a Range
Link: https://leetcode.com/problems/search-in-rotated-sorted-array-ii/ Given a sorted array of integ ...
- Tomcat7中开启gzip压缩功能的配置方法
使用gzip压缩可以减少数据传输大小,加快网页加载速度.很多大站都开启了gzip压缩,不过也有很多网站并没有开启gzip压缩,上次看了一篇文章说开启gzip压缩后对搜索引擎不友好,但从带宽和流量的角度 ...
- 为女票写的计算工作时间的SQL(二)
将非工作时间.非工作日.节假日去掉,计算工作时间,如下: 一.实现 -- 节假日表 CREATE TABLE Holiday ( id ) NOT NULL, DATE ), flag ) , PRI ...
- ms17010漏洞复现-2003
先使用Smbtouch模块检测一下是否有漏洞. 然后使用Doublepulsar写一个shellcode到本地. 生成成功后的截图: 再使用EternalRomance植入Doublepulsar后门 ...
- poj3067 Japan(树状数组)
转载请注明出处:http://blog.csdn.net/u012860063 题目链接:id=3067">http://poj.org/problem? id=3067 Descri ...
- UCOS2系统内核讲述_总体描述
Ⅰ.写在前面 学习本文之前可以参考我前面基于STM32硬件平台移植UCOS2的几篇文章,我将其汇总在一起: UCOS2_STM32F1移植详细过程(汇总文章) 要想学习,或使用系统配套的资源(如:信号 ...
- 已知问题汇总 (2013-11-30) - QQ空间, EXTJS
目前发现两个已知问题暂时无法得到解决: 1. QQ空间问题. 打开页面 http://user.qzone.qq.com/822994792/311, 点击 "xxx人赞" 这个链 ...
- 回文树(回文自动机) - URAL 1960 Palindromes and Super Abilities
Palindromes and Super Abilities Problem's Link: http://acm.timus.ru/problem.aspx?space=1&num=19 ...