HttpClient-4.5.2 实战

介绍:HttpClientFactory 相当与一个存储<String name,HttpClient instance>的map,不同业务需要不同的HttpClient。HttpClientUtil是一个工具类,以execute模版方法为核心,其他都是快捷方式。剥离出HttpClient实例化和HttpClientUtil工具方案集是为了减少冗余代码,缺点是每个HttpClientUtil方法都需要传入一个HttpClient实例。最后HttpClientUtilTest提供了一种单元测试方式。

pom.xml

<dependencies>  
        <dependency>  
            <groupId>org.apache.httpcomponents</groupId>  
            <artifactId>httpclient</artifactId>  
            <version>4.5.2</version>  
        </dependency>  
        ...
</dependencies> 
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> 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<NameValuePair> 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<byte[]>() {

                @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<String, String> params) {
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (org.apache.commons.collections.MapUtils.isNotEmpty(params)) {
            for (Map.Entry<String, String> 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<NameValuePair> 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<String>() {

                @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<String, Object> params) {
        List<NameValuePair> pairs = toPairs(params);
        return sendPost(httpclient,url, pairs);
    }

    private static List<NameValuePair> toPairs(Map<String, Object> params) {
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (MapUtils.isNotEmpty(params)) {
            for (Map.Entry<String, Object> 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<String, String> params, String fileName, byte[] fileData) {
        HttpPost post = new HttpPost(url);
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().addBinaryBody(fileName,
                fileData);
        for (Map.Entry<String, String> 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<String>() {

                @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<NameValuePair> 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);
    }


}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值