最近公司升级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);
}
}