HttpClient和ResetTemplate

相關(guān)依賴

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

Javadoc:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html

代碼

restTemplate配置類

D:\springbootdemo\src\main\java\cn\greenleaf\config\RestTemplateConfiguration.java

package cn.greenleaf.config;

import cn.greenleaf.common.RequestResponseLoggingInterceptor;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
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.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: Leon Liu
 * @Date: 2020/04/04/11:42
 * @Description:
 **/
@Configuration
public class RestTemplateConfiguration {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        RestTemplate restTemplate = builder.build();
        //使用HttpClient代替默認(rèn)的simpleClient
        restTemplate.setRequestFactory(clientHttpRequestFactory());
        // 使用 utf-8 編碼集的 converter 替換默認(rèn)的 converter(默認(rèn)的 StringHttpMessageConverter 的編碼集為"ISO-8859-1")
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        messageConverters.removeIf(converter -> converter instanceof StringHttpMessageConverter);
        //messageConverters.removeIf(converter -> converter instanceof MappingJackson2HttpMessageConverter); //去掉json自動解析
        messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
        //設(shè)置攔截器
        restTemplate.setInterceptors(Collections.singletonList(new RequestResponseLoggingInterceptor()));
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setHttpClient(httpClientBuilder().build());
        clientHttpRequestFactory.setConnectTimeout(3000); // 連接超時粱玲,毫秒
        clientHttpRequestFactory.setReadTimeout(10000); // 讀寫超時捅位,毫秒
        clientHttpRequestFactory.setConnectionRequestTimeout(2000);
        return clientHttpRequestFactory;
    }

    @Bean
    public HttpClientBuilder httpClientBuilder() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        //設(shè)置HTTP連接管理器
        httpClientBuilder.setConnectionManager(poolingConnectionManager());
        return httpClientBuilder;
    }

    @Bean
    public HttpClientConnectionManager poolingConnectionManager() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(registry);
        poolingConnectionManager.setMaxTotal(1000); // 連接池最大連接數(shù)
        poolingConnectionManager.setDefaultMaxPerRoute(100); // 每個主機(jī)的并發(fā)

        //啟動監(jiān)控線程定時清除不活動的連接
        Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(new IdleConnectionMonitorThread(poolingConnectionManager),
                1000, 500, TimeUnit.MILLISECONDS);
        return poolingConnectionManager;
    }

    public static class IdleConnectionMonitorThread extends Thread {

        private final HttpClientConnectionManager connMgr;
        private volatile boolean shutdown;

        public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
            super();
            this.connMgr = connMgr;
        }

        @Override
        public void run() {
            synchronized (this) {
                // 關(guān)閉失效的連接
                connMgr.closeExpiredConnections();
                // 可選的, 關(guān)閉5秒內(nèi)不活動的連接
                connMgr.closeIdleConnections(5, TimeUnit.SECONDS);
//                LoggerUtils.getLogger().debug("close idle connections");
            }
        }
    }
}

日志攔截器

D:\springbootdemo\src\main\java\cn\greenleaf\common\RequestResponseLoggingInterceptor.java

package cn.greenleaf.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;

import java.io.IOException;
import java.nio.charset.Charset;

/**
 * @Auther: Leon Liu
 * @Date: 2020/04/04/12:23
 * @Description:
 **/
public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
    {
        logRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        logResponse(response);

        //Add optional additional headers
        response.getHeaders().add("headerName", "VALUE");

        return response;
    }

    private void logRequest(HttpRequest request, byte[] body) throws IOException
    {
        if (log.isDebugEnabled())
        {
            log.debug("===========================request begin================================================");
            log.debug("URI         : {}", request.getURI());
            log.debug("Method      : {}", request.getMethod());
            log.debug("Headers     : {}", request.getHeaders());
            log.debug("Request body: {}", new String(body, "UTF-8"));
            log.debug("==========================request end================================================");
        }
    }

    private void logResponse(ClientHttpResponse response) throws IOException
    {
        if (log.isDebugEnabled())
        {
            log.debug("============================response begin==========================================");
            log.debug("Status code  : {}", response.getStatusCode());
            log.debug("Status text  : {}", response.getStatusText());
            log.debug("Headers      : {}", response.getHeaders());
            log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
            log.debug("=======================response end=================================================");
        }
    }
}

測試

D:\springbootdemo\src\test\java\cn\greenleaf\config\RestTemplateConfigurationTest.java

package cn.greenleaf.config;

import cn.greenleaf.domain.Cp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: Leon Liu
 * @Date: 2020/04/04/13:09
 * @Description:
 **/

@SpringBootTest
@RunWith(SpringRunner.class)
public class RestTemplateConfigurationTest {
    @Autowired
    RestTemplate restTemplate;

    @Test
    public void testGet() {
        restTemplate.getForObject("https://www.baidu.com", String.class);
    }

    @Test
    public void testPost() {
        Map map = new HashMap();
        map.put("offset", "0");
        map.put("page_size", "1");
        map.put("sign", "6fc9c71e4c5f5bf763f560d32b37bf17b5e6cd9e962ddd581e81b");
        Cp cp = restTemplate.postForObject("http://hybrid.xiaomi.com/test/audit_app_list/fetch/", null, Cp.class, map);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末携御,一起剝皮案震驚了整個濱河市也殖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腋颠,老刑警劉巖繁成,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淑玫,居然都是意外死亡巾腕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門絮蒿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尊搬,“玉大人,你說我怎么就攤上這事歌径』汆拢” “怎么了亲茅?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵回铛,是天一觀的道長。 經(jīng)常有香客問我克锣,道長茵肃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任袭祟,我火速辦了婚禮验残,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巾乳。我一直安慰自己您没,他們只是感情好鸟召,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著氨鹏,像睡著了一般欧募。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仆抵,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天跟继,我揣著相機(jī)與錄音,去河邊找鬼镣丑。 笑死舔糖,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的莺匠。 我是一名探鬼主播金吗,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼趣竣!你這毒婦竟也來了辽聊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤期贫,失蹤者是張志新(化名)和其女友劉穎跟匆,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體通砍,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玛臂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了封孙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迹冤。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虎忌,靈堂內(nèi)的尸體忽然破棺而出泡徙,到底是詐尸還是另有隱情,我是刑警寧澤膜蠢,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布堪藐,位于F島的核電站,受9級特大地震影響挑围,放射性物質(zhì)發(fā)生泄漏礁竞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一杉辙、第九天 我趴在偏房一處隱蔽的房頂上張望模捂。 院中可真熱鬧,春花似錦、人聲如沸狂男。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岖食。三九已至寓搬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間县耽,已是汗流浹背句喷。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兔毙,地道東北人唾琼。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像澎剥,于是被迫代替她去往敵國和親锡溯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容