HttpClient简单理解和使用

HttpClient的简介

  • 当有连接第一次使用的时候建立连接
  • 结束连接不关闭,归还到池中
  • 下次同个目的连接可以从池中直接获取
  • 定时清理过期连接
  • 定义需要的属性
  • 与http协议对接

使用场景

一是爬虫 ,但是我们不是面向监狱编程,我们是面向对象,所以大多是时候我们选择的是第二种,通过构建HttpClient连接池使用第三方的api。

依赖

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient</artifactId>
  <version>4.5.2</version>
</dependency>

代码

/**
* 自己编写一个连接池的工具类
*/
public class HttpClientUtil {

	/**
	 * 日志文件
	 */
	private static final Logger log = LoggerFactory.getLogger(HttpClientUtil.class);
	
	/**
	 * 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、.实际大小是该属性,该路由只能由1000的连接,既可以不考虑MaxTotal
	 */
	private static final int DEFAULT_MAX_PER_ROUTE = 1000;
	/**
	 * 设置连接池的大小
	 */
	private static final int MAX_TOTAL = 1000;

	/**
	 * 设置链接超时
	 */
	private static final int CONNECTION_TIMEOUT = 60000;
	/**
	 * 设置等待数据超时时间
	 */
	private static final int SOCKET_TIMEOUT = 60000;

	/**
	 * 初始化连接池
	 */
	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 &&"timeout".equalsIgnoreCase(param)) {
					try {
						return Long.parseLong(value) * 1000;
					} catch (Exception e) {
						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, null);
	}

	/**
	 * 
	 * @param uri
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static String sendPost(String uri, Map<String, String> param) throws Exception {
		return sendPost(uri, param, CONTENT_TYPE_FORM, CONTENT_TYPE_FORM, null);
	}

	private static String sendPost(String uri, Map<String, String> param, String reqContentType, String respContentType,
			Map<String, String> headers) 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);
			if (param != null && param.size() > 0) {
			//UrlEncodedFormEntity 的构造器只接受 List<? extends BasicNameValuePair> 等作为参数,不接受 Map所以需要做一个转换
				List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>(param.size());
				Iterator<Entry<String, String>> iterator = param.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, String> entry = iterator.next();
					params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
				}
				method.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
			}

			if (headers != null && headers.size() > 0) {
				Iterator<Entry<String, String>> iterator = headers.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, String> entry = iterator.next();
					method.addHeader(entry.getKey(), entry.getValue());
				}
			}

			HttpContext context = HttpClientContext.create();
			CloseableHttpResponse httpResponse = httpClient.execute(method, context);
			httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				responseBody = EntityUtils.toString(httpEntity, "UTF-8");
			}
		} catch (Exception e) {
			if (method != null) {
				method.abort();
			}
			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;
	}

	/**
	 * 执行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, Map<String, String> headers) throws Exception {
		return sendPost(uri, data, CONTENT_TYPE_JSON, CONTENT_TYPE_JSON, headers);
	}

	/**
	 * 执行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,
			Map<String, String> headers) 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")));
			//如果请求头有参数将请求头的参数进行添加
			if (headers != null && headers.size() > 0) {
				Iterator<Entry<String, String>> iterator = headers.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, String> entry = iterator.next();
					method.addHeader(entry.getKey(), entry.getValue());
				}

			}

			//固定写法,获取一些http的特定属性
			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();
			}
			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,Map<String, String> headers) throws Exception {
		return sendGet(uri, CONTENT_TYPE_JSON, CONTENT_TYPE_JSON,headers);
	}

	/**
	 * 执行GET 请求
	 * 
	 * @param uri             请求链接
	 * @param reqContentType  请求ContentType
	 * @param respContentType 响应ContentType
	 * @return String 响应数据
	 * @throws Exception 异常
	 */
	public static String sendGet(String uri, String reqContentType, String respContentType,Map<String, String> headers) 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();
			if (headers != null && headers.size() > 0) {
			//使用迭代器获取请求头信息
				Iterator<Entry<String, String>> iterator = headers.entrySet().iterator();
				while (iterator.hasNext()) {
					Entry<String, String> entry = iterator.next();
					method.addHeader(entry.getKey(), entry.getValue());
				}

			}
			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();
			}
			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) {
					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;
		}
		
		// 请求类型
		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;
	}
	
	
}

本人所写不一定是完全正确完善的,欢迎大家指导

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值