最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java http連接池的實現(xiàn)方式(帶有失敗重試等高級功能)

 更新時間:2024年04月28日 14:45:33   作者:苦蕎米  
這篇文章主要介紹了java http連接池的實現(xiàn)方式(帶有失敗重試等高級功能),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

java 本身提供的java.net.HttpURLConnection不支持連接池功能。

如果不想從頭實現(xiàn)的話,最好的方式便是引用第三方依賴包,目前是有一個特別不錯的,org.apache.httpcomponents:httpclient依賴

引入方式如下:

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.5.13</version>
</dependency>

使用httpclient依賴

在開始使用連接池之前,要學會如何使用httpclient去完成http請求,其請求方式與java的原生http請求完全不同。

其中CloseableHttpClient對象便是我們的http請求連接池,其實聲明方式會在下面介紹。

// 引用的包
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DoHttp {
	private static final Logger LOG = LoggerFactory.getLogger(DoHttp.class);
	// httpGet請求
	public static String get(CloseableHttpClient httpClient, String url) {
	    HttpGet httpGet = new HttpGet(url);
	    return doRequest(httpClient, url, httpGet);
	}
	// httpPost請求 (json格式)
	public static String jsonPost(CloseableHttpClient httpClient, String url, String json) {
	    HttpPost httpPost = new HttpPost(url);
	    httpPost.setHeader("Content-Type", "application/json");
	    StringEntity entity = new StringEntity(json, "UTF-8");
	    httpPost.setEntity(entity);
	    return doRequest(httpClient, url, httpPost);
	}
	// 統(tǒng)一的請求處理邏輯
	private static String doRequest(CloseableHttpClient httpClient, String url, HttpRequestBase httpRequest) {
	    try (CloseableHttpResponse response = httpClient.execute(httpRequest)) {
	        int code = response.getStatusLine().getStatusCode();
	        HttpEntity responseEntity = response.getEntity();
	        String responseBody = null;
	        if (responseEntity != null) {
	            responseBody = EntityUtils.toString(responseEntity);
	        }
	        if (code != 200) {
	            LOG.error("http post error, url: {}, code: {}, result: {}", url, code, responseBody);
	            return null;
	        }
	        return responseBody;
	    } catch (Exception e) {
	        LOG.error("http post error, url: {}", url, e);
	    }
	    return null;
	}
}

連接池的實現(xiàn)

連接池的配置類

如下:

public class HttpPoolConfig {
    /** http連接池大小 */
    public int httpPoolSize;
    /** http連接超時時間 */
    public int httpConnectTimeout;
    /** http連接池等待超時時間 */
    public int httpWaitTimeout;
    /** http響應包間隔超時時間 */
    public int httpSocketTimeout;
    /** http重試次數(shù) */
    public int httpRetryCount;
    /** http重試間隔時間 */
    public int httpRetryInterval;
    /** http監(jiān)控間隔時間 定時清理 打印連接池狀態(tài) */
    public int httpMonitorInterval;
    /** http關閉空閑連接的等待時間 */
    public int httpCloseIdleConnectionWaitTime;
}

連接池實現(xiàn)類

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
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.pool.PoolStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * http連接池
 */
public class HttpPool {

    private static final Logger LOG = LoggerFactory.getLogger(HttpPool.class);

    /**
     * 初始化連接池
     * @param httpPoolConfig 配置信息
     */
    public HttpPool(HttpPoolConfig httpPoolConfig) {
        PoolingHttpClientConnectionManager manager = buildHttpManger(httpPoolConfig);
        httpClient = buildHttpClient(httpPoolConfig, manager);
        monitorExecutor = buildMonitorExecutor(httpPoolConfig, manager);
    }

    private final CloseableHttpClient httpClient;
    private final ScheduledExecutorService monitorExecutor;

    /**
     * 連接池管理器
     */
    private PoolingHttpClientConnectionManager buildHttpManger(HttpPoolConfig httpPoolConfig) {
        LayeredConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslSocketFactory).build();
        PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry);
        manager.setMaxTotal(httpPoolConfig.httpPoolSize);
        manager.setDefaultMaxPerRoute(httpPoolConfig.httpPoolSize);
        return manager;
    }

    /**
     * 建立httpClient
     */
    private CloseableHttpClient buildHttpClient(HttpPoolConfig httpPoolConfig, PoolingHttpClientConnectionManager manager) {
        // 請求配置
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(httpPoolConfig.httpConnectTimeout)
                .setSocketTimeout(httpPoolConfig.httpSocketTimeout)
                .setConnectionRequestTimeout(httpPoolConfig.httpWaitTimeout)
                .build();
        // 失敗重試機制
        HttpRequestRetryHandler retryHandler = (e, c, context) -> {
            if (c > httpPoolConfig.httpRetryCount) {
                LOG.error("HttpPool request retry more than {} times", httpPoolConfig.httpRetryCount, e);
                return false;
            }
            if (e == null) {
                LOG.info("HttpPool request exception is null.");
                return false;
            }
            if (e instanceof NoHttpResponseException) {
                //服務器沒有響應,可能是服務器斷開了連接,應該重試
                LOG.error("HttpPool receive no response from server, retry");
                return true;
            }
            // SSL握手異常
            if (e instanceof InterruptedIOException // 超時
                    || e instanceof UnknownHostException // 未知主機
                    || e instanceof SSLException) { // SSL異常
                LOG.error("HttpPool request error, retry", e);
                return true;
            } else {
                LOG.error("HttpPool request unknown error, retry", e);
            }
            // 對于關閉連接的異常不進行重試
            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();
            return !(request instanceof HttpEntityEnclosingRequest);
        };
        // 構(gòu)建httpClient
        return HttpClients.custom().setDefaultRequestConfig(config)
                .setConnectionManager(manager).setRetryHandler(retryHandler).build();
    }

    /**
     * 建立連接池監(jiān)視器
     */
    private ScheduledExecutorService buildMonitorExecutor(HttpPoolConfig httpPoolConfig,
                                                          PoolingHttpClientConnectionManager manager) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                // 關閉過期連接
                manager.closeExpiredConnections();
                // 關閉空閑時間超過一定時間的連接
                manager.closeIdleConnections(httpPoolConfig.httpCloseIdleConnectionWaitTime, TimeUnit.MILLISECONDS);
                // 打印連接池狀態(tài)
                PoolStats poolStats = manager.getTotalStats();
                // max:最大連接數(shù), available:可用連接數(shù), leased:已借出連接數(shù), pending:掛起(表示當前等待從連接池中獲取連接的線程數(shù)量)
                LOG.info("HttpPool status {}", poolStats);
            }
        };
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        int time = httpPoolConfig.httpMonitorInterval;
        executor.scheduleAtFixedRate(timerTask, time, time, TimeUnit.MILLISECONDS);
        return executor;
    }

    /**
     * 關閉連接池
     */
    public void close() {
        try {
            httpClient.close();
            monitorExecutor.shutdown();
        } catch (Exception e) {
            LOG.error("HttpPool close http client error", e);
        }
    }

    /**
     * 發(fā)起get請求
     */
    public String get(String url) { return DoHttp.get(httpClient, url); }

    /**
     * 發(fā)起json格式的post請求
     */
    public String jsonPost(String url, String json) { return DoHttp.jsonPost(httpClient, url, json); }
}

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • java類訪問權(quán)限與成員訪問權(quán)限解析

    java類訪問權(quán)限與成員訪問權(quán)限解析

    這篇文章主要針對java類訪問權(quán)限與成員訪問權(quán)限進行解析,對類與成員訪問權(quán)限進行驗證,感興趣的小伙伴們可以參考一下
    2016-02-02
  • Java入門交換數(shù)組中兩個元素的位置

    Java入門交換數(shù)組中兩個元素的位置

    在Java中,交換數(shù)組中的兩個元素是基本的數(shù)組操作,下面我們將詳細介紹如何實現(xiàn)這一操作,以及在實際應用中這種技術(shù)的重要性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-09-09
  • Java利用StringBuffer替換特殊字符的方法實現(xiàn)

    Java利用StringBuffer替換特殊字符的方法實現(xiàn)

    這篇文章主要介紹了Java利用StringBuffer替換特殊字符的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • Spring中TransactionSynchronizationManager的使用詳解

    Spring中TransactionSynchronizationManager的使用詳解

    這篇文章主要介紹了Spring中TransactionSynchronizationManager的使用詳解,TransactionSynchronizationManager是事務同步管理器,監(jiān)聽事務的操作,來實現(xiàn)在事務前后可以添加一些指定操作,需要的朋友可以參考下
    2023-09-09
  • java Wrapper類基本用法詳解

    java Wrapper類基本用法詳解

    在本篇文章里小編給大家整理的是一篇關于java Wrapper類基本用法詳解,有興趣的朋友們可以參考下。
    2021-01-01
  • MyBatis特殊字符轉(zhuǎn)義攔截器問題針對(_、\、%)

    MyBatis特殊字符轉(zhuǎn)義攔截器問題針對(_、\、%)

    這篇文章主要介紹了MyBatis特殊字符轉(zhuǎn)義攔截器問題針對(_、\、%),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Spring?Security實現(xiàn)分布式系統(tǒng)授權(quán)方案詳解

    Spring?Security實現(xiàn)分布式系統(tǒng)授權(quán)方案詳解

    這篇文章主要介紹了Spring?Security實現(xiàn)分布式系統(tǒng)授權(quán),本節(jié)完成注冊中心的搭建,注冊中心采用Eureka,本文通過示例代碼圖文相結(jié)合給大家介紹的非常詳細,需要的朋友可以參考下
    2022-02-02
  • Java內(nèi)存區(qū)域與內(nèi)存溢出異常的詳細探討

    Java內(nèi)存區(qū)域與內(nèi)存溢出異常的詳細探討

    這篇文章主要介紹了Java內(nèi)存區(qū)域與內(nèi)存溢出異常的相關資料,分析異常原因并提供解決策略,如參數(shù)調(diào)整、代碼優(yōu)化等,幫助開發(fā)者排查內(nèi)存問題,需要的朋友可以參考下
    2025-05-05
  • Java中的CAS和自旋鎖詳解

    Java中的CAS和自旋鎖詳解

    這篇文章主要介紹了Java中的CAS和自旋鎖詳解,CAS算法(Compare And Swap),即比較并替換,是一種實現(xiàn)并發(fā)編程時常用到的算法,Java并發(fā)包中的很多類都使用了CAS算法,需要的朋友可以參考下
    2023-10-10
  • 淺析SpringMVC中的適配器HandlerAdapter

    淺析SpringMVC中的適配器HandlerAdapter

    這篇文章主要介紹了SpringMVC中的適配器HandlerAdapter的相關資料,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01

最新評論

永顺县| 方城县| 门头沟区| 东宁县| 呼伦贝尔市| 道孚县| 阿图什市| 南涧| 赤水市| 通化市| 信阳市| 岐山县| 文安县| 浮山县| 茌平县| 措勤县| 十堰市| 万州区| 东平县| 广安市| 上林县| 湖州市| 綦江县| 疏勒县| 新津县| 汝城县| 宣汉县| 浦北县| 巨野县| 临沂市| 兴仁县| 徐闻县| 永清县| 达孜县| 会理县| 建水县| 望谟县| 霸州市| 潜江市| 崇仁县| 前郭尔|