介绍:HttpClientFactory 相当与一个存储
pom.xml
org.apache.httpcomponents
httpclient
4.5.2
...
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.pool.PoolStats;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
/**
* 描述:
*
* @author jianlin.zhu
* @create 2020-01-16 11:39
**/
public class HttpClientFactory {
private static Logger logger = LoggerFactory.getLogger(HttpClientFactory.class);
public static CloseableHttpClient httpclient1;
public static CloseableHttpClient httpclient2;
public static CloseableHttpClient getInstance(String name) {
if (name == null) {
throw new NullPointerException("name is null");
}
switch (name) {
case "httpclient1":
return httpclient1;
case "httpclient2":
return httpclient2;
}
throw new IllegalArgumentException("unfound name:" + name);
}
private static final int TIME_OUT = 30000;
private static final int CONNECT_TIMEOUT = 5000;
private static final int CONNECT_REQUEST_TIMEOUT = 3000;
private static final int MAX_CONN = 1000;
private static final int MAX_PER_ROUTE = 200;
private static final int VALIDATE_AFTER_INACTIVITY_MS = 1000;
private static final long DEFAULT_KEEP_ALIVE_MS = 60 * 1000; // 如果没有约定,则默认定义时长为60s
static {
createClient1();
createClient2();
}
private static void createClient1() {
String clientName = "httpclient1";
PoolingHttpClientConnectionManager pm = new PoolingHttpClientConnectionManager();
pm.setMaxTotal(MAX_CONN);
pm.setDefaultMaxPerRoute(MAX_PER_ROUTE);
pm.setValidateAfterInactivity(VALIDATE_AFTER_INACTIVITY_MS);
IdleConnectionMonitorThread cleanerThread = new IdleConnectionMonitorThread(pm,clientName);
cleanerThread.setDaemon(true);
cleanerThread.start();
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(TIME_OUT)
.setConnectionRequestTimeout(CONNECT_REQUEST_TIMEOUT).build();
httpclient1 = HttpClients.custom().setConnectionManager(pm).setKeepAliveStrategy(SIMPLE_KEEP_ALIVE_STRATEGY).setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(createSSLConnectionSocketFactory()).setRetryHandler(new DefaultHttpRequestRetryHandler(0,
false)).build();
}
private static SSLConnectionSocketFactory createSSLConnectionSocketFactory(){
SSLConnectionSocketFactory sslConnectionSocketFactory = null;
try {
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);
}catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e ){
throw new RuntimeException("init error",e);
}
if(sslConnectionSocketFactory == null){
throw new RuntimeException("create sslConnectionSocketFactory error");
}
return sslConnectionSocketFactory;
}
private static void createClient2() {
String clientName = "httpclient2";
PoolingHttpClientConnectionManager pm = new PoolingHttpClientConnectionManager();
pm.setMaxTotal(MAX_CONN);
pm.setDefaultMaxPerRoute(MAX_PER_ROUTE);
pm.setValidateAfterInactivity(VALIDATE_AFTER_INACTIVITY_MS);
IdleConnectionMonitorThread cleanerThread = new IdleConnectionMonitorThread(pm,clientName);
cleanerThread.setDaemon(true);
cleanerThread.start();
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(TIME_OUT)
.setConnectionRequestTimeout(CONNECT_REQUEST_TIMEOUT).build();
httpclient2 = HttpClients.custom().setConnectionManager(pm).setKeepAliveStrategy(SIMPLE_KEEP_ALIVE_STRATEGY).setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(createSSLConnectionSocketFactory()).setRetryHandler(new DefaultHttpRequestRetryHandler(1,
true)).build();
}
private final static ConnectionKeepAliveStrategy SIMPLE_KEEP_ALIVE_STRATEGY = new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
HeaderElement he = it.nextElement();
String param = he.getName();
String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
}
}
return DEFAULT_KEEP_ALIVE_MS;
}
};
public static void main(String[] args) throws Exception {
HttpClientUtil.sendGet(HttpClientFactory.getInstance("httpclient1"), "http://localhost:8088",new HashMap<>());
}
public static class IdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private final String clientName;
private volatile boolean shutdown;
public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr,String clientName){
super();
this.connMgr = connMgr;
this.clientName = clientName;
this.setName("IdleConnectionMonitorThread-"+clientName);
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
if(connMgr instanceof PoolingHttpClientConnectionManager){
PoolStats poolStats = ((PoolingHttpClientConnectionManager)connMgr).getTotalStats();
logger.info("{} pool stats {}",clientName,poolStats);
}
// Close expired connections
connMgr.closeExpiredConnections();
// Optionally, close connections
// that have been idle longer than 30 sec
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
// terminate
}
}
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
}
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 描述:
*
* @author jianlin.zhu
* @create 2020-01-16 12:52
**/
public class HttpClientUtil {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
private static final String DEFAULT_CHARSET = "utf-8";
public static T execute(CloseableHttpClient httpClient, HttpUriRequest request, ResponseHandler extends T> responseHandler,
HttpContext httpContext) throws ClientProtocolException, IOException {
T result;
HttpResponse response = null;
response = httpClient.execute(request, httpContext);
try {
result = responseHandler.handleResponse(response);
} catch (Exception t) {
if (response != null) {
EntityUtils.consume(response.getEntity());
}
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
if (t instanceof IOException) {
throw (IOException) t;
}
throw new UndeclaredThrowableException(t);
}
EntityUtils.consume(response.getEntity());
return result;
}
public static byte[] sendGetBytes(CloseableHttpClient httpclient,String url, List params) {
if (CollectionUtils.isNotEmpty(params)) {
url = url + "?" + URLEncodedUtils.format(params, DEFAULT_CHARSET);
}
HttpGet get = new HttpGet(url);
byte[] result = null;
try {
result = execute(httpclient,get, new ResponseHandler() {
@Override
public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toByteArray(response.getEntity());
} else {
logger.error("http error code:{}", response.getStatusLine().getStatusCode());
}
return null;
}
}, null);
} catch (ClientProtocolException e) {
logger.error("ClientProtocolException", e);
} catch (Exception e) {
if (e instanceof SocketTimeoutException) {
logger.error("occur timeout exception", e);
} else if (e instanceof UnknownHostException) {
logger.error("occur unknow host exception", e);
} else {
logger.error("occur undealed exception", e);
}
}
return result;
}
public static String sendGet(CloseableHttpClient httpclient,String url, Map params) {
List pairs = new ArrayList();
if (org.apache.commons.collections.MapUtils.isNotEmpty(params)) {
for (Map.Entry entry : params.entrySet()) {
pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
return sendGetWithNameValuePair(httpclient,url, pairs);
}
public static String sendGetWithNameValuePair(CloseableHttpClient httpclient,String url, List params) {
if (CollectionUtils.isNotEmpty(params)) {
url = url + "?" + URLEncodedUtils.format(params, DEFAULT_CHARSET);
}
HttpGet get = new HttpGet(url);
String result = null;
try {
result = execute(httpclient,get, new ResponseHandler() {
@Override
public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toString(response.getEntity());
} else {
logger.error("http error code:{},errorInfo:{}", response.getStatusLine().getStatusCode(),
EntityUtils.toString(response.getEntity()));
}
return null;
}
}, null);
} catch (ClientProtocolException e) {
get.abort();// TODO
System.out.println("ClientProtocolException abort");
logger.error("ClientProtocolException", e);
} catch (Exception e) {
get.abort();// TODO
System.out.println(e.getMessage() + "abort");
if (e instanceof SocketTimeoutException) {
logger.error("occur timeout exception", e);
} else if (e instanceof UnknownHostException) {
logger.error("occur unknow host exception", e);
} else {
logger.error("occur undealed exception", e);
}
}
return result;
}
public static String sendPost(CloseableHttpClient httpclient,String url, Map params) {
List pairs = toPairs(params);
return sendPost(httpclient,url, pairs);
}
private static List toPairs(Map params) {
List pairs = new ArrayList();
if (MapUtils.isNotEmpty(params)) {
for (Map.Entry entry : params.entrySet()) {
String value = (null == entry.getValue()) ? null : String.valueOf(entry.getValue());
pairs.add(new BasicNameValuePair(entry.getKey(), value));
}
}
return pairs;
}
public static String sendPostWithFile(CloseableHttpClient httpclient,String url, Map params, String fileName, byte[] fileData) {
HttpPost post = new HttpPost(url);
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().addBinaryBody(fileName,
fileData);
for (Map.Entry entry : params.entrySet()) {
multipartEntityBuilder.addTextBody(entry.getKey(), entry.getValue());
}
post.setEntity(multipartEntityBuilder.build());
return executePost(httpclient,post);
}
public static String sendPostWithJSON(CloseableHttpClient httpclient,String url, String params) {
HttpPost post = new HttpPost(url);
post.setEntity(new StringEntity(params, ContentType.APPLICATION_JSON));
return executePost(httpclient,post);
}
private static String executePost(CloseableHttpClient httpclient,HttpPost post) {
String result = null;
try {
result = execute(httpclient,post, new ResponseHandler() {
@Override
public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
if (response.getStatusLine().getStatusCode() == 200) {
return EntityUtils.toString(response.getEntity());
} else {
logger.error("http error code:{},errorInfo:{}", response.getStatusLine().getStatusCode(),
EntityUtils.toString(response.getEntity()));
}
return null;
}
}, null);
} catch (ClientProtocolException e) {
logger.error("ClientProtocolException", e);
} catch (Exception e) {
if (e instanceof SocketTimeoutException) {
logger.error("occur timeout exception", e);
} else if (e instanceof UnknownHostException) {
logger.error("occur unknow host exception", e);
} else {
logger.error("occur undealed exception", e);
}
}
return result;
}
public static String sendPost(CloseableHttpClient httpclient,String url, List params) {
HttpPost post = new HttpPost(url);
try {
post.setEntity(new UrlEncodedFormEntity(params));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return executePost(httpclient,post);
}
}
import org.junit.Ignore;
import org.junit.Test;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
/**
* 描述:
*
* @author jianlin.zhu
* @create 2020-01-08 22:54
**/
public class HttpClientUtilTest {
@Test
@Ignore
public void test0()throws Exception{
Thread[] threads = new Thread[10];
for(int i=0;i<10;++i) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for(int i=0;i<10;++i) {
HttpClientUtil.sendGet(HttpClientFactory.getInstance("httpclient1"),"http://localhost:8088/ok.htm", new HashMap<>());
}
}
});
threads[i].start();
}
for(int i=0;i<10;++i) {
threads[i].join();
}
TimeUnit.SECONDS.sleep(10* 3600);
}
}