HttpClient連接池的實現


 

1、連接池初始化工具類的創建

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.DnsResolver;
import org.apache.http.conn.HttpConnectionFactory;
import org.apache.http.conn.ManagedHttpClientConnection;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultHttpResponseParserFactory;
import org.apache.http.impl.conn.ManagedHttpClientConnectionFactory;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.conn.SystemDefaultDnsResolver;
import org.apache.http.impl.io.DefaultHttpRequestWriterFactory;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author zs
 * @description http連接池的相關獲取信息
 */
@Slf4j
public class HttpClientUtils {

    private static PoolingHttpClientConnectionManager manager = null;
    private static CloseableHttpClient httpClient = null;

    public static synchronized CloseableHttpClient getHttpClient() {
        if (httpClient == null) {
            System.out.println("---------------------------------------------------------創建");

            //注冊訪問協議相關的Socket工廠
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
                    .<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
                    .build();

            //HttpConnection 工廠:配置寫請求/解析響應處理器
            HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connectionFactory
                    = new ManagedHttpClientConnectionFactory(
                            DefaultHttpRequestWriterFactory.INSTANCE,
                            DefaultHttpResponseParserFactory.INSTANCE);
            //DNS 解析器
            DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
            //創建池化連接管理器
            manager = new PoolingHttpClientConnectionManager(socketFactoryRegistry, connectionFactory, dnsResolver);
            //默認為Socket配置
            SocketConfig defaultSocketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
            manager.setDefaultSocketConfig(defaultSocketConfig);
            //設置整個連接池的最大連接數
            manager.setMaxTotal(300);
            //每個路由的默認最大連接,每個路由實際最大連接數由DefaultMaxPerRoute控制,而MaxTotal是整個池子的最大數
            //設置過小無法支持大並發(ConnectionPoolTimeoutException) Timeout waiting for connection from pool
            //每個路由的最大連接數
            manager.setDefaultMaxPerRoute(200);
            //在從連接池獲取連接時,連接不活躍多長時間后需要進行一次驗證,默認為2s
            manager.setValidateAfterInactivity(5 * 1000);
            //默認請求配置
            RequestConfig defaultRequestConfig = RequestConfig.custom()
                    //設置連接超時時間,2s
                    .setConnectTimeout(2 * 1000)
                    //設置等待數據超時時間,5s
                    .setSocketTimeout(5 * 1000)
                    //設置從連接池獲取連接的等待超時時間
                    .setConnectionRequestTimeout(2000)
                    .build();
            //創建HttpClient
            httpClient = HttpClients.custom()
                    .setConnectionManager(manager)
                    //連接池不是共享模式
                    .setConnectionManagerShared(false)
                    //定期回收空閑連接
                    .evictIdleConnections(60, TimeUnit.SECONDS)
                    // 定期回收過期連接
                    .evictExpiredConnections()
                    //連接存活時間,如果不設置,則根據長連接信息決定
                    .setConnectionTimeToLive(60, TimeUnit.SECONDS)
                    //設置默認請求配置
                    .setDefaultRequestConfig(defaultRequestConfig)
                    //連接重用策略,即是否能keepAlive
                    .setConnectionReuseStrategy(DefaultConnectionReuseStrategy.INSTANCE)
                    //長連接配置,即獲取長連接生產多長時間
                    .setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE)
                    //設置重試次數,默認是3次,當前是禁用掉(根據需要開啟)
                    .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                    .build();

            //JVM 停止或重啟時,關閉連接池釋放掉連接(跟數據庫連接池類似)
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        if (httpClient != null) {
                            httpClient.close();
                        }
                    } catch (IOException e) {
                        log.error("error when close httpClient:{}", e);
                    }
                }
            });
        }
        return httpClient;
    }
}

2、get請求獲取信息

public static void testGet() {
        try {
            //第一步:把HttpClient使用的jar包添加到工程中。
            //第二步:創建一個HttpClient的測試類
            //第三步:創建測試方法。
            //第四步:創建一個HttpClient對象
            CloseableHttpClient httpClient = HttpClientUtils.getHttpClient();
            //第五步:創建一個HttpGet對象,需要制定一個請求的url
            HttpGet get = new HttpGet("http://www.baidu.com");
            //第六步:執行請求。
            CloseableHttpResponse response = httpClient.execute(get);
            //第七步:接收返回結果。HttpEntity對象。
            HttpEntity entity = response.getEntity();
            //第八步:取響應的內容。
            String html = EntityUtils.toString(entity);
            System.out.println(html);
            //第九步:關閉response、HttpClient
            response.close();
            httpClient.close();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

3、post請求獲取信息

public void testPost() {
        try {
            //	第一步:創建一個httpClient對象
            CloseableHttpClient httpClient = HttpClientUtils.getHttpClient();
            //	第二步:創建一個HttpPost對象。需要指定一個url
            HttpPost post=new HttpPost("http://www.baidu.com");
            //	第三步:創建一個list模擬表單,list中每個元素是一個NameValuePair對象
            List<NameValuePair> formList=new ArrayList<NameValuePair>();
            formList.add(new BasicNameValuePair("name","張三"));
            formList.add(new BasicNameValuePair("pass","1234"));
            //	第四步:需要把表單包裝到Entity對象中。StringEntity
            StringEntity entity=new UrlEncodedFormEntity(formList,"utf-8");
            post.setEntity(entity);
            //	第五步:執行請求。
            CloseableHttpResponse response = httpClient.execute(post);
            //	第六步:接收返回結果
            HttpEntity httpEntity=response.getEntity();
            String result = EntityUtils.toString(httpEntity);
            System.out.println(result);
            //	第七步:關閉流。
            response.close();
            httpClient.close();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

  

4、相關請求及數據封裝

/**
     * post請求傳輸map數據
     *
     * @param url      請求地址
     * @param map      傳遞的參數
     * @param encoding 參數編碼
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String sendPostDataByMap(String url, Map<String, String> map, String encoding) {
        String result = "";
        CloseableHttpResponse response = null;
        try {
            // 創建httpclient對象
            CloseableHttpClient httpClient = HttpClientUtils.getHttpClient();
            // 創建post方式請求對象
            HttpPost httpPost = new HttpPost(url);
            // 裝填參數
            List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
            if (map != null) {
                for (Entry<String, String> entry : map.entrySet()) {
                    nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
            // 設置參數到請求對象中
            httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, encoding));
            // 設置header信息
            // 指定報文頭【Content-type】、【User-Agent】
            httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
            httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            // 執行請求操作,並拿到結果(同步阻塞)
            response = httpClient.execute(httpPost);
            // 獲取結果實體
            // 判斷網絡連接狀態碼是否正常(0--200都數正常)
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
            }
            // 釋放鏈接
            response.close();
            return result;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // 釋放鏈接
            try {
                response.close();
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
            return result;
        }
    }

    /**
     * post請求傳輸json數據
     *
     * @param url      請求地址
     * @param json     傳遞的參數
     * @param encoding 參數編碼
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static String sendPostDataByJson(String url, String json, String encoding) {
        String result = "";
        CloseableHttpResponse response = null;
        try {
            // 創建httpclient對象
            CloseableHttpClient httpClient = HttpClientUtils.getHttpClient();
            // 創建post方式請求對象
            HttpPost httpPost = new HttpPost(url);
            // 設置參數到請求對象中
            StringEntity stringEntity = new StringEntity(json, ContentType.APPLICATION_JSON);
            // "utf-8"
            stringEntity.setContentEncoding(encoding);
            httpPost.setEntity(stringEntity);
            // 執行請求操作,並拿到結果(同步阻塞)
            response = httpClient.execute(httpPost);
            // 獲取結果實體
            // 判斷網絡連接狀態碼是否正常(0--200都數正常)
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
            }
            // 釋放鏈接
            response.close();
            return result;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            // 釋放鏈接
            try {
                response.close();
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
            return result;
        }
    }

    /**
     * get請求傳輸數據
     *
     * @param url
     * @param encoding
     * @return
     * @throws ClientProtocolException
     * @throws IOException
     */
    public String sendGetData(String url, String encoding) {
        String result = "";
        CloseableHttpResponse response = null;
        try {
            // 創建httpclient對象
            CloseableHttpClient httpClient = HttpClientUtils.getHttpClient();

            // 創建get方式請求對象
            HttpGet httpGet = new HttpGet(url);
            httpGet.addHeader("Content-type", "application/json");
            // 通過請求對象獲取響應對象
            response = httpClient.execute(httpGet);

            // 獲取結果實體
            // 判斷網絡連接狀態碼是否正常(0--200都數正常)
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
            }
            // 釋放鏈接
            response.close();
            return result;
        } catch (Exception e) {
            try {
                response.close();
            } catch (IOException ex) {
                log.error(ex.getMessage(), ex);
            }
            return result;
        }
    }

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM