http-可支持高并发下的httpClient工具类,http请求工具_执意丨的博客-程序员资料

技术标签: httpclent  基础  http请求工具  

maven依赖

<dependencies>
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpmime</artifactId>
		<version>4.5.2</version>
	</dependency>
	<dependency>
		<groupId>org.apache.httpcomponents</groupId>
		<artifactId>httpcore</artifactId>
		<version>4.4.6</version>
	</dependency>
</dependencies>

代码

package com.wei.processor

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * httpclient 请求工具类 
 * httpclient 连接池
 * @author weisibin
 * @date 2020-5-13 09:39:57
 */
@Slf4j
public class HttpClientUtil {
	
	/**
	 * http链接池
	 */
	private static PoolingHttpClientConnectionManager cm = null;
	/**
	 * http客户端
	 */
	private static CloseableHttpClient httpClient = null;
	/**
	 * from-请求/响应   类型
	 */
	public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded;charset=UTF-8";
	/**
	 * json-请求/响应   类型
	 */
	public static final String CONTENT_TYPE_JSON = "application/json;charset=UTF-8";
	
	/**
	 * 长连接时间保持设置
	 */
	private static final int HTTP_DEFAULT_KEEP_TIME = 60000;

	/**
	 * 1、MaxtTotal是整个池子的大小; 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如:
	 * MaxtTotal=400 DefaultMaxPerRoute=200
	 * 而我只连接到http://sishuok.com时,到这个主机的并发最多只有200;而不是400; 而我连接到http://sishuok.com 和
	 * http://qq.com时,到每个主机的并发最多只有200;即加起来是400(但不能超过400);
	 * 所以起作用的设置是DefaultMaxPerRoute。
	 */
	private static final int DEFAULT_MAX_PER_ROUTE = 1000;
	/**
	 * 设置连接池的大小
	 */
	private static final int MAX_TOTAL = 1000;

	/**
	 * 设置链接超时
	 */
	private static final int CONNECTION_TIMEOUT = 5000;
	/**
	 * 设置等待数据超时时间
	 */
	private static final int SOCKET_TIMEOUT = 15000;
	/**
	 * 初始化连接池
	 */
	private static synchronized void initPools() {
		if (httpClient == null) {
			cm = new PoolingHttpClientConnectionManager();
			cm.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
			cm.setMaxTotal(MAX_TOTAL);
			httpClient = HttpClients.custom().setKeepAliveStrategy(defaultStrategy).setConnectionManager(cm).build();
		}
	}
	/**
	 * 长连接保持设置 Http connection keepAlive 设置
	 */
	private static ConnectionKeepAliveStrategy defaultStrategy = new ConnectionKeepAliveStrategy() {
		@Override
		public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
			HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
			int keepTime = HTTP_DEFAULT_KEEP_TIME;
			while (it.hasNext()) {
				HeaderElement he = it.nextElement();
				String param = he.getName();
				String value = he.getValue();
				if (value != null && param.equalsIgnoreCase("timeout")) {
					try {
						return Long.parseLong(value) * 1000;
					} catch (Exception e) {
						e.printStackTrace();
						log.error("format KeepAlive timeout exception, exception:{}", e.toString());
						throw e;
					}
				}
			}
			return keepTime * 1000;
		}
	};

	/**
	 * 执行http post
	 * 请求 默认采用Content-Type:application/json
	 * 响应 默认采用Content-Type:application/json
	 * @param uri  请求地址
	 * @param data 请求数据
	 * @return String 返回是数据
	 * @throws Exception 请求异常
	 */
	public static String sendPost(String uri, String data) throws Exception {
		return sendPost(uri,data,CONTENT_TYPE_JSON,CONTENT_TYPE_JSON);
	}

	/**
	 * 执行http post请求
	 * @param uri 请求地址
	 * @param data 请求数据
	 * @param reqContentType 请求content-type
	 * @param respContentType 响应content-type
	 * @return String 返回请求结果
	 * @throws Exception 异常
	 */
	public static String sendPost(String uri, String data, String reqContentType, String respContentType)
			throws Exception {
		long startTime = System.currentTimeMillis();
		HttpEntity httpEntity = null;
		HttpEntityEnclosingRequestBase method = null;
		String responseBody = "";
		try {
			if (httpClient == null) {
				initPools();
			}
			method = (HttpEntityEnclosingRequestBase) getRequest(uri, HttpPost.METHOD_NAME, reqContentType,
					respContentType);
			method.setEntity(new StringEntity(data, Charset.forName("UTF-8")));
			HttpContext context = HttpClientContext.create();
			CloseableHttpResponse httpResponse = httpClient.execute(method, context);
			httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				responseBody = EntityUtils.toString(httpEntity, "UTF-8");
				log.debug("post请求信息:\n请求URL: {},\n请求参数{},\n返回状态码:{},\n返回结果:{}", uri, data,
						httpResponse.getStatusLine().getStatusCode(), responseBody);
			}
		} catch (Exception e) {
			if (method != null) {
				method.abort();
			}
			e.printStackTrace();
			log.error("execute post request exception, url:{},exception:{}, cost time(ms):{}", uri, e.toString(),
					System.currentTimeMillis() - startTime);
			throw e;
		} finally {
			if (httpEntity != null) {
				try {
					EntityUtils.consumeQuietly(httpEntity);
				} catch (Exception e) {
					e.printStackTrace();
					log.error("execute post request exception, url:{},exception:{}, cost time(ms):{}", uri,
							e.toString(), System.currentTimeMillis() - startTime);
					throw e;
				}
			}
		}
		return responseBody;
	}

	/**
	 * 执行GET 请求
	 * 请求 默认采用Content-Type:application/json
	 * 响应 默认采用Content-Type:application/json
	 * @param uri 请求链接
	 * @return String 请求结果
	 * @throws Exception 异常
	 */
	public static String sendGet(String uri) throws Exception {
		return sendGet(uri,CONTENT_TYPE_JSON,CONTENT_TYPE_JSON);
	}

	/**
	 * 执行GET 请求
	 * @param uri 请求链接
	 * @param reqContentType 请求ContentType
	 * @param respContentType 响应ContentType
	 * @return String 响应数据
	 * @throws Exception 异常
	 */
	public static String sendGet(String uri, String reqContentType, String respContentType) throws Exception {
		long startTime = System.currentTimeMillis();
		HttpEntity httpEntity = null;
		HttpRequestBase method = null;
		String responseBody = "";
		try {
			if (httpClient == null) {
				initPools();
			}
			method = getRequest(uri, HttpGet.METHOD_NAME, reqContentType, respContentType);
			HttpContext context = HttpClientContext.create();
			CloseableHttpResponse httpResponse = httpClient.execute(method, context);
			httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				responseBody = EntityUtils.toString(httpEntity, "UTF-8");
				log.debug("get请求信息:\n请求URL: {},\n返回状态码:{},\n返回结果:{}", uri,
						httpResponse.getStatusLine().getStatusCode(), responseBody);
			}
		} catch (Exception e) {
			if (method != null) {
				method.abort();
			}
			e.printStackTrace();
			log.error("execute get request exception, url:{},exception:{}, cost time(ms):{}", uri, e.toString(),
					System.currentTimeMillis() - startTime);
			throw e;
		} finally {
			if (httpEntity != null) {
				try {
					EntityUtils.consumeQuietly(httpEntity);
				} catch (Exception e) {
					e.printStackTrace();
					log.error("execute get request exception, url:{},exception:{}, cost time(ms):{}", uri,
							e.toString(), System.currentTimeMillis() - startTime);
					throw e;
				}
			}
		}
		return responseBody;
	}

	/**
	 * 创建请求
	 * @param uri 请求url
	 * @param methodName 请求的方法类型
	 * @param reqContentType 请求ContentType
	 * @param respContentType 响应ContentType
	 * @return HttpRequestBase http请求的基本实现对象
	 */ 
	private static HttpRequestBase getRequest(String uri, String methodName, String reqContentType,
			String respContentType) {
		HttpRequestBase method = null;

		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT)
				.setConnectTimeout(CONNECTION_TIMEOUT).setConnectionRequestTimeout(CONNECTION_TIMEOUT)
				.setExpectContinueEnabled(false).build();
		if (HttpPut.METHOD_NAME.equalsIgnoreCase(methodName)) {
			method = new HttpPut(uri);
		} else if (HttpPost.METHOD_NAME.equalsIgnoreCase(methodName)) {
			method = new HttpPost(uri);
		} else if (HttpGet.METHOD_NAME.equalsIgnoreCase(methodName)) {
			method = new HttpGet(uri);
		} else {
			method = new HttpPost(uri);
		}
		if (StringUtils.isBlank(reqContentType)) {
			reqContentType = CONTENT_TYPE_FORM;
		}
		if (StringUtils.isBlank(respContentType)) {
			respContentType = CONTENT_TYPE_JSON;
		}
		// 请求类型
		method.addHeader("Content-Type", reqContentType);
		method.addHeader("Accept", respContentType);
		method.setConfig(requestConfig);
		return method;
	}
	/**
	 * 获取 httpClient
	 * @return CloseableHttpClient
	 */
	public static CloseableHttpClient getHttpClient() {
		return httpClient;
	}
	
	/**
	 * 获取 httpClient连接池
	 * @return PoolingHttpClientConnectionManager
	 */
	public static PoolingHttpClientConnectionManager getHttpConnectionManager() {
		return cm;
	}
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ab52262879/article/details/96478760

智能推荐

zookeeper学习笔记(二)_vincent_nkcs的博客-程序员资料

六 ZooKeeper Shell客户端连接 ` zkCli.sh -server {ip}`创建节点create [-s] [-e] {path} {data} {acl}-s表示序列化,-e表示临时节点,若不指定则表示持久节点,path为节点路径,data为数据,acl用来进行权限控制。zookeeper为自带节点。读取节点ls / ls {path}查看指定节点下的第一级所有...

从Xamarin.Essentials谈Xamarin库的封装_dotNET跨平台的博客-程序员资料

编者语:Xamarin在国内的推广还需要努力,其实这真的是移动端开发的一大福音,毕竟用一份代码的时间可以生成iOS/Android/Windows/Linux/macOS...

HLS直播取流过程演示_摄像头hls取流方式_小哥山水之间的博客-程序员资料

一、HLS是什么HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。是苹果公司QuickTime X和iPhone软件系统的一部分。 它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8)playlist文件,用于寻找可

哔哩哔哩 B站视频引用到自己的网站的方法_视频放b站再引用_咫尺云天的博客-程序员资料

先上个例子&lt;iframe height=100% width=100% src="//player.bilibili.com/player.html?bvid=BV1LC4y1s7gd&amp;page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"&gt; &lt;...

编译和移植qt-embedded-linux-opensource-src-4.5.3_qt embedded qlinuxfb_lhembed的博客-程序员资料

最初的动机是不想使用qtopia来开发qt界面,在网上搜索到qt/embedded也是可以解决的。在网上搜索了好多关于这方面的内容,我找了一个亲身实践的来讲吧。开发平台:Ubuntu 9.10目标平台:hfrk s3c2410交叉工具:arm-linux 版本4.1.2qt版本:qt-embedded-linux-opensource-src-4.5.3 下载地址:ftp://ftp.qt.nokia.com/qt/source/qt-embedded-linux-opensource-src-4.5.3.

随便推点

spring源码学习之路---IOC实现原理(三)_weixin_30425949的博客-程序员资料

作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可。上一章我们已经初步认识了BeanFactory和BeanDefinition,一个是IOC的核心工厂接口,一个是IOC的bean定义接口,上章提到说我们无法让BeanFactory持有一...

链表面试题(一)_不负韶华-z的博客-程序员资料

本文所有的函数都是在上一篇单链表的基础上建立的。1、从尾到头打印链表分析:如下图所示,单链表为1、2、3、4、NULL,题目要求从尾到头打印,即打印的效果为4、3、2、1、NULL。我们可以用递归和循环来实现这一功能。 递归:递归的结束条件为pNodet为空,代码比较简单。循环:可以定义两个指针,一个用来遍历链表,一个用来结束循环。如图所示,用pNode来遍历链表,让pNode从...

免费下载PPT的网站_一个努力小白的博客-程序员资料

免费得PPT下载网站一、officeplusofficeplus,这个是微软官方的模板库哦,并且网站除了PPT模板,还有word的模板网站:http://www.officeplus.cn/Template/Home.shtml二、51PPT模板网这是一个有口皆碑的PPT网站了,虽然网站设计一般,但是模版下载确实比较方便。只要点击某篇模板,找到“下载地址”,即可下载。网址:http://www.51pptmoban.com/三、第一PPT第一PP是国内最早一批提供P

mysql 获取单个科目的平均分_weixin_30745553的博客-程序员资料

mysql&gt; select * from test;+----+----------+-------+-----------+| id | name | score | subject |+----+----------+-------+-----------+| 1 | xiaoming | 89 | shuxue || ...

推荐文章

热门文章

相关标签