httpclient5 工具类

最近公司升级httpclient,从httpclient-4.3.2.jar升级到httpclient5-5.1.3.jar,写了个工具类供参考,可以去mvn仓库下载https://mvnrepository.com/或者添加maven依赖。

        <dependency>
            <groupId>org.apache.httpcomponents.client5</groupId>
            <artifactId>httpclient5</artifactId>
            <version>5.1.3</version>
        </dependency>

发布时间
2020年2月 httpclient从4.5直接升级了到5.0.

主要升级内容
1、支持HTTP/2
2、新的异步HTTP接口
3、重构reactor io模式,改进基于reactor 的NIO,使得性能和拓展性更好。
4、不论服务端是阻塞还是异步的实现,httpclient5均能支持服务端的过滤。例如横切协议(cross-cutting protocol)的握手,和用户认证授权。
5、支持reactive流的API
6、使用严格连接有限保证的方式重构连接池的实现。通过减少全局连接池的锁,连接池在高并发下获得更好的性能。
7、新的不严格连接有限保证连接池的实现。通过去除全局的连接池锁获得更高的性能。
8、更改包名
9、更改maven的groupId

包初探
从支持HHTP/2到新的连接池实现。从版本号的跳跃和包名和groupId的变更都显示着这次的变动非常之大。
那我们从包的角度来看看这次的变动。

maven依赖
发现groupId多了一个client5,artifactId也多了一个5,version从4变成了5

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

<dependency>
        <groupId>org.apache.httpcomponents.client5</groupId>
        <artifactId>httpclient5</artifactId>
        <version>5.1.3</version>
    </dependency>
包名的变动
import org.apache.http.impl.client.CloseableHttpClient;//原包名
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;//5.0 包名

升级发现包名路径,方法都变了,需要重新写一个工具类。贴上代码供参考!

package com.figo.demo.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.InputStreamEntity;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.apache.hc.core5.util.Timeout;

import com.figo.util.log.MonitorLogger;

public class HttpClientUtils {
	/**
	 * 日志.
	 */
	private static MonitorLogger logger = MonitorLogger.getLogger(HttpClientUtils.class);
	
	public static CloseableHttpClient httpClient = HttpClients.createDefault();
	static {
		logger.info("设置httpclient5超时时间,tls,连接池等属性");
		// 设置超时时间
		RequestConfig config = RequestConfig.custom().setConnectTimeout(Timeout.ofMilliseconds(60000L))
				.setConnectionRequestTimeout(Timeout.ofMilliseconds(60000L))
				.setResponseTimeout(Timeout.ofMilliseconds(60000L)).build();
		// 未设置支持ssl
//		httpClient = HttpClients.custom().setDefaultRequestConfig(config).build();
		// httpclient5经测试不设置支持ssl,也能调用https接口
		try {
			httpClient = HttpClients.custom().setDefaultRequestConfig(config)
					.setConnectionManager(getHttpClientConnectionManager()).build();
		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
			httpClient = HttpClients.createDefault();
			e.printStackTrace();
		}

	}

	private static HttpClientConnectionManager getHttpClientConnectionManager()
			throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		// 设置连接池最大连接数1000,最大并发数200,及支持ssl,tls
		return PoolingHttpClientConnectionManagerBuilder.create().setMaxConnTotal(1000).setMaxConnPerRoute(200)
				.setSSLSocketFactory(getSslConnectionSocketFactory()).build();
	}

	/**
	 * 支持SSL
	 *
	 * @return SSLConnectionSocketFactory
	 */
	private static SSLConnectionSocketFactory getSslConnectionSocketFactory()
			throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
		TrustStrategy acceptingTrustStrategy = (x509Certificates, s) -> true;
		SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
		return new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
		//链接tls版本协议,不指定也可以
//		return new SSLConnectionSocketFactory(sslContext,  new String[] {"TLSv1.1","TLSv1.2","TLSv1.3"},
//				  null, new NoopHostnameVerifier());

	}

	/**
	 * get方式请求
	 * 
	 * @param url
	 * @return
	 */
	public static String get(String url) {
		return get(url, null, null);
	}

	/**
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static String get(String url, Map<String, Object> headers, Map<String, Object> params) {
		logger.info("httpclient5 get start url="+url+"headers="+headers+",params="+params);

		String resultContent = null;
		HttpGet httpGet = new HttpGet(url);

		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpGet.addHeader(entry.getKey(), entry.getValue());
			}
		}
		if (params != null && params.size() > 0) {
			// 表单参数
			List<NameValuePair> nvps = new ArrayList<>();
			// GET 请求参数,如果中文出现乱码需要加上URLEncoder.encode
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
			}
			// 增加到请求 URL 中
			try {
				URI uri = new URIBuilder(new URI(url)).addParameters(nvps).build();
				httpGet.setUri(uri);
			} catch (URISyntaxException e) {
				throw new RuntimeException(e);
			}

		}

		try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
			// 获取状态码
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK
			HttpEntity entity = response.getEntity();
			// 获取响应信息
			resultContent = EntityUtils.toString(entity,"UTF-8");
			logger.info("httpclient5 get end url="+url+"headers="+headers+",params="+params+",result="+resultContent);
			// 确保流被完全消费
			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("Exception httpclient5 get url="+url+"headers="+headers+",params="+params+",exception="+e.getStackTrace());

		}

		return resultContent;
	}

	/**
	 * post form请求
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static String postForm(String url, Map<String, String> headers, Map<String, Object> params) {
		logger.info("httpclient5 postForm start url="+url+"headers="+headers+",params="+params);

		String result = null;
		HttpPost httpPost = new HttpPost(url);
		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpPost.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
			}
		}
		httpPost.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
		// 表单参数
		List<NameValuePair> nvps = new ArrayList<>();
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
		}
//注意编码为UTF-8,否则中文会出现乱码
		httpPost.setEntity(new UrlEncodedFormEntity(nvps,Charset.forName("UTF-8")));

		try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK

			HttpEntity entity = response.getEntity();
			// 获取响应信息
			result = EntityUtils.toString(entity,"UTF-8");
			logger.info("httpclient5 postForm end url="+url+"headers="+headers+",params="+params+",result="+result);

			// 确保流被完全消费
			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("Exception httpclient5 postForm url="+url+"headers="+headers+",params="+params+",exception="+e.getStackTrace());

		}

		return result;
	}

	/**
	 * post form请求,返回Response,有些请求需要拿到header
	 * 
	 * @param url
	 * @param params
	 * @return
	 */
	public static CloseableHttpResponse postFormReturnResponse(String url, Map<String, Object> headers,
			Map<String, Object> params) {
		CloseableHttpResponse response = null;
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");

		// 设置header
		if (headers != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				httpPost.addHeader(entry.getKey(), entry.getValue());
			}
		}
		// 表单参数
		List<NameValuePair> nvps = new ArrayList<>();
		// POST 请求参数
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
		}
		httpPost.setEntity(new UrlEncodedFormEntity(nvps,Charset.forName("UTF-8")));

		try {
			response = httpClient.execute(httpPost);
//			Header[] header=response.getHeaders();
			System.out.println(response.getVersion()); // HTTP/1.1
			System.out.println(response.getCode()); // 200
			System.out.println(response.getReasonPhrase()); // OK
//
//			HttpEntity entity = response.getEntity();
//			// 获取响应信息
//			result = EntityUtils.toString(entity);
//			// 确保流被完全消费
//			EntityUtils.consume(entity);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return response;
	}

	/**
	 * post json请求
	 * 
	 * @param url
	 * @param jsonBody
	 * @return
	 */
	public static String postJson(String url, String jsonBody) {
		logger.info("httpclient5 postJson start url="+url+",jsonBody="+jsonBody);

		String result = null;
		HttpPost httpPost = new HttpPost(url);
		httpPost.addHeader("Content-Type","application/json;charset=UTF-8");
		httpPost.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));

		try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
			// 获取响应信息
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
		} catch (IOException | ParseException e) {
			e.printStackTrace();
			logger.info("Exception postJson postForm url="+url+",jsonBody="+jsonBody+",exception="+e.getStackTrace());

		}
		logger.info("httpclient5 postJson end url="+url+",result="+result);

		return result;
	}

	/**
	 * post stream请求(file,json,xml转stream)
	 * 
	 * @param url
	 * @param jsonBody
	 * @return
	 */
	public static String postStream(String url, String params, ContentType contentType) {
		String result = null;
		final HttpPost httppost = new HttpPost(url);
		InputStream inputStream = new ByteArrayInputStream(new String(params).getBytes());
		final InputStreamEntity reqEntity = new InputStreamEntity(inputStream, -1, contentType);
		// 也可以使用 FileEntity 的形式
		// FileEntity reqEntity = new FileEntity(new File(params),
		// ContentType.APPLICATION_JSON);

		httppost.setEntity(reqEntity);
		try (final CloseableHttpResponse response = httpClient.execute(httppost)) {
			System.out.println("----------------------------------------");
			System.out.println(response.getCode() + " " + response.getReasonPhrase());
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * getAsync异步请求,回调获取结果
	 *
	 * @param url
	 * @return
	 */
	public static String getAsync(String url) {
		try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
			// 开始 http clinet
			httpclient.start();
			// 根据请求响应情况进行回调操作
//            CountDownLatch latch = new CountDownLatch(1);
			SimpleHttpRequest request = SimpleHttpRequests.get(url);
			httpclient.execute(request, new FutureCallback<SimpleHttpResponse>() {
				@Override
				public void completed(SimpleHttpResponse response2) {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + "->" + response2.getCode());
				}

				@Override
				public void failed(Exception ex) {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + "->" + ex);
				}

				@Override
				public void cancelled() {
//                    latch.countDown();
					System.out.println("getAsync:" + request.getRequestUri() + " cancelled");
				}

			});
//            latch.await();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return null;
	}

	public static void main(String[] args) {
		String newPayUrl="http://localhost:8080/test/jsp/test.jsp";
		String response=postJson(newPayUrl,"{'key1':'123'}");
		System.out.println(response);

	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值