天天看點

httpclient連接配接池配置

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.2</version>
      

</dependency>

package com.iscas.datasong.lib.util;

import com.iscas.datasong.lib.common.DataSongException;
import com.iscas.datasong.lib.common.Status;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;


public class BaseHttpClientPoolUtil {
    /*最大連接配接數,應該放在配置檔案内*/
    private int maxTotal = 800;
    /*每個路由的最大連接配接數*/
    private int maxPerRoute = 200;
    /**
     * 向服務端請求逾時時間設定(機關:毫秒)
     */
    private static int SERVER_REQUEST_TIME_OUT = 2000;
    /**
     * 服務端響應逾時時間設定(機關:毫秒)
     */
    private static int SERVER_RESPONSE_TIME_OUT = 2000;

    /*從連接配接池擷取連接配接的逾時時間*/
    private static int CONNECTION_REQUEST_TIME_OUT = 2000;
    /*重試次數*/
    private static int retry = 3;
    //    /*是否關閉socket緩沖*/
//    private boolean tcpNoDelay = false;
//    /*關閉socket後,是否可立即重用端口*/
//    private boolean soReuseAddress = true;
//    /*接收資料等待逾時時間毫秒*/
//    private int soTimeout = 500;
//    /*socket最大等待關閉連接配接時間秒*/
//    private int soLinger = 60;
    private static volatile PoolingHttpClientConnectionManager pollManager = null;

    public BaseHttpClientPoolUtil() throws NoSuchAlgorithmException {
        init();
    }

    private void init() throws NoSuchAlgorithmException {
        if (pollManager == null) {
            synchronized (BaseHttpClientPoolUtil.class){
                if(pollManager == null){
                    LayeredConnectionSocketFactory sslsf = null;
                    sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
                    Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                            .register("https", sslsf)
                            .register("http", new PlainConnectionSocketFactory())
                            .build();
                    pollManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                    pollManager.setMaxTotal(maxTotal);
                    pollManager.setDefaultMaxPerRoute(maxPerRoute);

                    //某個host的路由數配置,覆寫default,暫時不配置
                    //pollManager.setMaxPerRoute(new HttpRoute(new HttpHost("some host", 80)), 150);

//        //socket配置
//        SocketConfig socketConfig = SocketConfig.custom()
//                .setTcpNoDelay(tcpNoDelay)     //是否立即發送資料,設定為true會關閉Socket緩沖,預設為false
//                .setSoReuseAddress(soReuseAddress) //是否可以在一個程序關閉Socket後,即使它還沒有釋放端口,其它程序還可以立即重用端口
//                .setSoTimeout(soTimeout)       //接收資料的等待逾時時間,機關ms
//                .setSoLinger(soLinger)         //關閉Socket時,要麼發送完所有資料,要麼等待60s後,就關閉連接配接,此時socket.close()是阻塞的
//                .setSoKeepAlive(true)    //開啟監視TCP連接配接是否有效
//                .build();
//        pollManager.setDefaultSocketConfig(socketConfig);
                }

            }
        }
    }

    public CloseableHttpClient getHttpClient(int SERVER_REQUEST_TIME_OUT, int SERVER_RESPONSE_TIME_OUT, int CONNECTION_REQUEST_TIME_OUT) {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SERVER_REQUEST_TIME_OUT).setConnectTimeout(SERVER_RESPONSE_TIME_OUT).build();
        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pollManager)
                .setRetryHandler(getHttpRequestRetryHandler())
                .build();
        return httpClient;
    }

    public RequestConfig getDefaultRequestConfig() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SERVER_REQUEST_TIME_OUT)
                .setConnectTimeout(SERVER_RESPONSE_TIME_OUT)
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIME_OUT)
                .build();
        return requestConfig;
    }


    public HttpRequestRetryHandler getHttpRequestRetryHandler(){
        HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {

            public boolean retryRequest(
                    IOException exception,
                    int executionCount,
                    HttpContext context) {
                if (executionCount >= retry) {
                    // 如果已經重試了5次,就放棄
                    return false;
                }
                if (exception instanceof InterruptedIOException) {
                    // 逾時
                    return false;
                }
                if (exception instanceof UnknownHostException) {
                    // 目标伺服器不可達
                    return false;
                }
                if (exception instanceof ConnectTimeoutException) {
                    // 連接配接被拒絕
                    return false;
                }
                if (exception instanceof SSLException) {
                    // ssl握手異常
                    return false;
                }
                HttpClientContext clientContext = HttpClientContext.adapt(context);
                HttpRequest request = clientContext.getRequest();
                boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
                if (idempotent) {
                    // 如果請求是幂等的,就再次嘗試
                    return true;
                }
                return false;
            }

        };
        return myRetryHandler;
    }

    public CloseableHttpClient getHttpClient() {
        RequestConfig requestConfig = getDefaultRequestConfig();
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig)
                .setConnectionManager(pollManager)
                .setRetryHandler(getHttpRequestRetryHandler())
                .build();
        return httpClient;
    }

    public String doGet(String url) throws DataSongException {
        if (DataSongStringUtils.isEmpty(url)) {
            throw new DataSongException(Status.PARAM_ERROR, "param can not be null");
        }

        //    url = validateUrl(url);

        CloseableHttpResponse response = null;
        String body = null;
        try {
            HttpGet get = new HttpGet(url);

            get.addHeader("Content-type", "application/json; charset=utf-8");
            get.setHeader("Accept", "application/json");

            response = getHttpClient().execute(get);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                body = EntityUtils.toString(response.getEntity());
            } else {
                throw new DataSongException(Status.SERVER_ERROR, String.format("error code [%s]", statusCode));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != response) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }
    /**
     * 執行post方法
     * @param url
     * @param parameter
     * @return
     */
    public String doPost(String url, String parameter) throws DataSongException {
        if(DataSongStringUtils.isEmpty(url)){
            throw new DataSongException(Status.PARAM_ERROR, "url can not be null");
        }

        //    url = validateUrl(url);

        String body = null;
        CloseableHttpResponse response = null;
        try {

            HttpPost httpPost = new HttpPost(url);

            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            if(!DataSongStringUtils.isEmpty(parameter)) {
                httpPost.setEntity(new StringEntity(parameter, Charset.forName("UTF-8")));
            }

            response = getHttpClient().execute(httpPost);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                body = EntityUtils.toString(response.getEntity());
            } else {
                throw new DataSongException(Status.SERVER_ERROR, String.format("error code []",statusCode));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null!=response){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }

    public String doPut(String url, String parameter) throws DataSongException {
//    if(DataSongStringUtils.isEmpty(parameter) || DataSongStringUtils.isEmpty(url)){
//       throw new DataSongException(Status.PARAM_ERROR, "param can not be null");
//    }

        //    url = validateUrl(url);

        String body = null;
        CloseableHttpResponse response = null;
        try {
            HttpPut httpPost = new HttpPut(url);

            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            if(null!=parameter){
                httpPost.setEntity(new StringEntity(parameter, Charset.forName("UTF-8")));
            }
            response = getHttpClient().execute(httpPost);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                body = EntityUtils.toString(response.getEntity());
            } else {
                throw new DataSongException(Status.SERVER_ERROR, String.format("%s ,error code [%s]",response.getStatusLine().getReasonPhrase(),statusCode));
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null!=response){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }

    public String doDelete(String url) throws DataSongException {
        if(DataSongStringUtils.isEmpty(url)){
            throw new DataSongException(Status.PARAM_ERROR, "param can not be null");
        }

        //    url = validateUrl(url);

        String body = null;
        CloseableHttpResponse response = null;
        try {
            HttpDelete delete = new HttpDelete(url);

            delete.addHeader("Content-type", "application/json; charset=utf-8");
            delete.setHeader("Accept", "application/json");

            response = getHttpClient().execute(delete);

            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == HttpStatus.SC_OK) {
                // Read the response body
                body = EntityUtils.toString(response.getEntity());
            } else {
                throw new DataSongException(Status.SERVER_ERROR, String.format("error code []",statusCode));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(null!=response){
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return body;
    }

    protected String validateUrl(String url){
        if(url.contains("?")){
            url = url.replace("?","%26");
        }

        if(url.contains("&")){
            url = url.replace("&","%3F");
        }

        if(url.contains("|")){
            url = url.replace("|","%124");
        }

        if(url.contains("=")){
            url = url.replace("=","%3D");
        }

        if(url.contains("#")){
            url = url.replace("#","%23");
        }

        if(url.contains("/")){
            url = url.replace("/","%2F");
        }

        if(url.contains("+")){
            url = url.replace("+","%2B");
        }

        if(url.contains("%")){
            url = url.replace("%","%25");
        }

        if(url.contains(" ")){
            url = url.replace(" ","%20");
        }

        return url;
    }
}