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

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

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

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

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

引入方式如下:

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

使用httpclient依賴

在開(kāi)始使用連接池之前,要學(xué)會(huì)如何使用httpclient去完成http請(qǐng)求,其請(qǐng)求方式與java的原生http請(qǐng)求完全不同。

其中CloseableHttpClient對(duì)象便是我們的http請(qǐng)求連接池,其實(shí)聲明方式會(huì)在下面介紹。

// 引用的包
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請(qǐng)求
	public static String get(CloseableHttpClient httpClient, String url) {
	    HttpGet httpGet = new HttpGet(url);
	    return doRequest(httpClient, url, httpGet);
	}
	// httpPost請(qǐng)求 (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)一的請(qǐ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;
	}
}

連接池的實(shí)現(xiàn)

連接池的配置類

如下:

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

連接池實(shí)現(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) {
        // 請(qǐng)求配置
        RequestConfig config = RequestConfig.custom()
                .setConnectTimeout(httpPoolConfig.httpConnectTimeout)
                .setSocketTimeout(httpPoolConfig.httpSocketTimeout)
                .setConnectionRequestTimeout(httpPoolConfig.httpWaitTimeout)
                .build();
        // 失敗重試機(jī)制
        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) {
                //服務(wù)器沒(méi)有響應(yīng),可能是服務(wù)器斷開(kāi)了連接,應(yīng)該重試
                LOG.error("HttpPool receive no response from server, retry");
                return true;
            }
            // SSL握手異常
            if (e instanceof InterruptedIOException // 超時(shí)
                    || e instanceof UnknownHostException // 未知主機(jī)
                    || e instanceof SSLException) { // SSL異常
                LOG.error("HttpPool request error, retry", e);
                return true;
            } else {
                LOG.error("HttpPool request unknown error, retry", e);
            }
            // 對(duì)于關(guān)閉連接的異常不進(jìn)行重試
            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() {
                // 關(guān)閉過(guò)期連接
                manager.closeExpiredConnections();
                // 關(guān)閉空閑時(shí)間超過(guò)一定時(shí)間的連接
                manager.closeIdleConnections(httpPoolConfig.httpCloseIdleConnectionWaitTime, TimeUnit.MILLISECONDS);
                // 打印連接池狀態(tài)
                PoolStats poolStats = manager.getTotalStats();
                // max:最大連接數(shù), available:可用連接數(shù), leased:已借出連接數(shù), pending:掛起(表示當(dāng)前等待從連接池中獲取連接的線程數(shù)量)
                LOG.info("HttpPool status {}", poolStats);
            }
        };
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        int time = httpPoolConfig.httpMonitorInterval;
        executor.scheduleAtFixedRate(timerTask, time, time, TimeUnit.MILLISECONDS);
        return executor;
    }

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

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

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

總結(jié)

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

相關(guān)文章

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

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

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

    Java入門(mén)交換數(shù)組中兩個(gè)元素的位置

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

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

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

    Spring中TransactionSynchronizationManager的使用詳解

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

    java Wrapper類基本用法詳解

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

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

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

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

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

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

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

    Java中的CAS和自旋鎖詳解

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

    淺析SpringMVC中的適配器HandlerAdapter

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

最新評(píng)論

沈阳市| 抚松县| 德化县| 南充市| 都兰县| 镇宁| 乌拉特后旗| 民县| 汉中市| 凤翔县| 德保县| 滨海县| 合肥市| 北京市| 甘孜县| 商丘市| 肥乡县| 永福县| 武夷山市| 建湖县| 渭源县| 新兴县| 昌图县| 宁强县| 饶阳县| 那坡县| 津南区| 南阳市| 屏山县| 托里县| 玉田县| 怀远县| 驻马店市| 古浪县| 手游| 日照市| 页游| 灌云县| 繁昌县| 孟州市| 尼玛县|