一、前言
一说到HttpClient大家都有各种方式,网上也都有各种demo;总结网上加上自己实践的,附下面一个通用httpClientUtils类;平时记录住,开发项目用到时,之间cv操作;
二、依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
三、源码
public final class HttpClientUtils {
public static String url = "xxxxx";
private static PoolingHttpClientConnectionManager manager;
private static String EMPTY_STR = "";
private static String UTF_8 = "UTF-8";
private static void init(){
if (manager == null){
manager = new PoolingHttpClientConnectionManager();
//整个链接池最大连接数
manager.setMaxTotal(50);
//每个路由最大连接数
manager.setDefaultMaxPerRoute(5);
}
}
/**
* 通过连接池获取httpClient
* @return
*/
private static CloseableHttpClient getHttpClient(){
init();
return HttpClients.custom().setConnectionManager(manager).build();
}
/**
* @param url
* @return
*/
public static String getHttpRequest(String url) {
HttpGet httpGet = new HttpGet(url);
return getResult(httpGet);
}
public static String getHttpRequest(String url, Map<String, Object> params) throws URISyntaxException {
URIBuilder ub = new URIBuilder(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
ub.setParameters(pairs);
HttpGet httpGet = new HttpGet(ub.build());
return getResult(httpGet);
}
public static String getHttpRequest(String url, Map<String, Object> headers, Map<String, Object> params)
throws URISyntaxException {
URIBuilder ub = new URIBuilder();
ub.setPath(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
ub.setParameters(pairs);
HttpGet httpGet = new HttpGet(ub.build());
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
}
return getResult(httpGet);
}
public static String postHttpRequest(String url) {
HttpPost httpPost = new HttpPost(url);
return getResult(httpPost);
}
public static String postHttpRequest(String url,String json) {
HttpPost httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(json,"utf-8");//解决中文乱码问题
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
return getResult(httpPost);
}
public static String postHttpRequest(String url, Map<String, Object> params) throws UnsupportedEncodingException {
HttpPost httpPost = new HttpPost(url);
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
// 配置请求的超时设置
int timeout=1000*10;
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(timeout)
.setConnectTimeout(timeout)
.setSocketTimeout(timeout)
.build();
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
httpPost.setConfig(requestConfig);
return getResult(httpPost);
}
public static String postHttpRequest(String url, Map<String, Object> headers, Map<String, Object> params)
throws UnsupportedEncodingException {
HttpPost httpPost = new HttpPost(url);
for (Map.Entry<String, Object> param : headers.entrySet()) {
httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
}
ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
return getResult(httpPost);
}
private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
for (Map.Entry<String, Object> param : params.entrySet()) {
pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
}
return pairs;
}
/**
* 处理http请求
* @param request
* @return
*/
private static String getResult(HttpRequestBase request) {
CloseableHttpClient httpClient = getHttpClient();
try {
System.out.println("");
CloseableHttpResponse response = httpClient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
response.close();
return result;
}
} catch (IOException e) {
e.printStackTrace();
}
return EMPTY_STR;
}
public static void main(String[] args) throws UnsupportedEncodingException {
long startTime = System.currentTimeMillis();
Map<String,Object> param = new HashMap<>();
param.put("bizCode","xxx");
param.put("time","xxx");
param.put("pageNum","1");
param.put("pageSize","20");
String result = HttpClientUtils.postHttpRequest(url,param);
long endTime = System.currentTimeMillis();
System.out.println(result);
System.out.println("耗时:"+ (endTime-startTime)/1000+"秒" );
}
}
HTTPClient 连接池常见问题
- 如何判断连接是否可以保持?
检查返回response报文头的Transfer-Encoding字段,若该字段值存在且不为chunked,则连接不保持,直接关闭。
检查返回的response报文头的Content-Length字段,若该字段值为空或者格式不正确(多个长度,值不是整数),则连接不保持,直接关闭。
检查返回的response报文头的Connection字段(若该字段不存在,则为Proxy-Connection字段)值:
如果这俩字段都不存在,则1.1版本默认为保持, 1.0版本默认为连接不保持,直接关闭。
如果字段存在,若字段值为close 则连接不保持,直接关闭;若字段值为keep-alive则连接标记为保持。
- 保持多长时间?
保持时间计时开始时间为连接交换至连接池的时间。 保持时长计算规则为:获取response中 Keep-Alive字段中timeout值,若该存在,则保持时间为 timeout值*1000,单位毫秒。若不存在,则连接保持时间设置为-1,表示为无穷。
- 保持过程中如何保证连接没有失效?
很难保证。传统阻塞I/O模型,只有当I/O操做的时候,socket才能响应I/O事件。当TCP连接交给连接管理器后,它可能还处于“保持连接”的状态,但是无法监听socket状态和响应I/O事件。如果这时服务器将连接关闭的话,客户端是没法知道这个状态变化的,从而也无法采取适当的手段来关闭连接。
针对这种情况,HttpClient采取一个策略,通过一个后台的监控线程定时的去检查连接池中连接是否还“新鲜”,如果过期了,或者空闲了一定时间则就将其从连接池里删除掉。ClientConnectionManager提供了 closeExpiredConnections和closeIdleConnections两个方法。