springboot2.x | restTemplate 的簡(jiǎn)單使用

http 協(xié)議

http 協(xié)議是一個(gè)用于傳輸超媒體文檔(例如html)的應(yīng)用層的協(xié)議啄寡。他是為了web瀏覽器和web 服務(wù)器之間的通訊而設(shè)計(jì)的
可以參考:
MDN web Docs

http1.1

現(xiàn)在web中用的最廣的協(xié)議。
HTTP/1.1 主要的功能要點(diǎn):

  • 增加了 HEAD彼水、POST 等新方法
  • 增加了響應(yīng)狀態(tài)碼,標(biāo)記可能的錯(cuò)誤原因
  • 引入了協(xié)議版本號(hào)概念
  • 引入了 HTTP Header(頭部)的概念,讓 HTTP 處理請(qǐng)求和響應(yīng)更加靈活
  • 傳輸?shù)臄?shù)據(jù)不再僅限于文本
  • 增加了 PUT、DELETE 等新的方法续室;
  • 增加了緩存管理和控制;
  • 明確了連接管理谒养,允許持久連接挺狰;
  • 允許響應(yīng)數(shù)據(jù)分塊(chunked)明郭,利于傳輸大文件;
  • 強(qiáng)制要求 Host 頭丰泊,讓互聯(lián)網(wǎng)主機(jī)托管成為可能薯定。

http2

HTTP/1.1 發(fā)布之后,整個(gè)互聯(lián)網(wǎng)世界呈現(xiàn)出了爆發(fā)式的增長(zhǎng)瞳购,度過(guò)了十多年的“快樂(lè)時(shí)光”话侄,更涌現(xiàn)出了 Facebook、Twitter学赛、淘寶年堆、京東等互聯(lián)網(wǎng)新貴。

這期間也出現(xiàn)了一些對(duì) HTTP 不滿(mǎn)的意見(jiàn)盏浇,主要就是連接慢变丧,無(wú)法跟上迅猛發(fā)展的互聯(lián)網(wǎng),但 HTTP/1.1 標(biāo)準(zhǔn)一直“巋然不動(dòng)”绢掰,無(wú)奈之下人們只好發(fā)明各式各樣的“小花招”來(lái)緩解這些問(wèn)題痒蓬,比如以前常見(jiàn)的切圖、JS 合并等網(wǎng)頁(yè)優(yōu)化手段滴劲。

終于有一天攻晒,搜索巨頭 Google 忍不住了,首先開(kāi)發(fā)了自己的瀏覽器 Chrome班挖,然后推出了新的 SPDY 協(xié)議炎辨,并在 Chrome 里應(yīng)用于自家的服務(wù)器,如同十多年前的網(wǎng)景與微軟一樣聪姿,從實(shí)際的用戶(hù)方來(lái)“倒逼”HTTP 協(xié)議的變革,這也開(kāi)啟了第二次的“瀏覽器大戰(zhàn)”乙嘀。

歷史再次重演末购,不過(guò)這次的勝利者是 Google,Chrome 目前的全球的占有率超過(guò)了 60%虎谢。Google 借此順勢(shì)把 SPDY 推上了標(biāo)準(zhǔn)的寶座盟榴,互聯(lián)網(wǎng)標(biāo)準(zhǔn)化組織以 SPDY 為基礎(chǔ)開(kāi)始制定新版本的 HTTP 協(xié)議,最終在 2015 年發(fā)布了 HTTP/2婴噩,RFC 編號(hào) 7540擎场。

HTTP/2 的制定充分考慮了現(xiàn)今互聯(lián)網(wǎng)的現(xiàn)狀:寬帶、移動(dòng)几莽、不安全迅办,在高度兼容 主要的特點(diǎn)有:

  • 二進(jìn)制協(xié)議,不再是純文本
  • 可發(fā)起多個(gè)請(qǐng)求章蚣,廢棄了 1.1 里的管道
  • 使用專(zhuān)用算法壓縮頭部站欺,減少數(shù)據(jù)傳輸量
  • 允許服務(wù)器主動(dòng)向客戶(hù)端推送數(shù)據(jù)
  • 增強(qiáng)了安全性,“事實(shí)上”要求加密通信

restTemplate

RestTemplate 是從 Spring3.0 開(kāi)始支持的一個(gè) HTTP 請(qǐng)求工具,它提供了常見(jiàn)的REST請(qǐng)求方案的模版矾策,例如 GET 請(qǐng)求磷账、POST 請(qǐng)求、PUT 請(qǐng)求贾虽、DELETE 請(qǐng)求以及一些通用的請(qǐng)求執(zhí)行方法 exchange 以及 execute逃糟。

  • 調(diào)用RestTemplate的默認(rèn)構(gòu)造函數(shù),RestTemplate對(duì)象在底層通過(guò)使用java.net包下的實(shí)現(xiàn)創(chuàng)建HTTP 請(qǐng)求蓬豁,
  • 可以通過(guò)使用ClientHttpRequestFactory指定不同的HTTP請(qǐng)求方式绰咽。
    ClientHttpRequestFactory接口主要提供了三種實(shí)現(xiàn)方式
    1、SimpleClientHttpRequestFactory方式庆尘,此處生成SimpleBufferingClientHttpRequest剃诅,使用HttpURLConnection創(chuàng)建底層的Http請(qǐng)求連接
    2、HttpComponentsClientHttpRequestFactory方式驶忌,此處生成HttpComponentsClientHttpRequest矛辕,使用http client來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求
    3、OkHttp3ClientHttpRequestFactory方式付魔,此處生成OkHttp3ClientHttpRequest聊品,使用okhttp來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)請(qǐng)求

注入 restTemplate

@Configuration
public class RestTemplateConfig {

    /**
     * 方法1 :無(wú)參數(shù)的默認(rèn)
     *
     * @return
     */
//    @Bean
//    public RestTemplate restTemplate(){
//        return new RestTemplate();
//    }


    /**
     * 方法2 :
     * 用 ClientHttpRequestFactory 來(lái)創(chuàng)建http請(qǐng)求
     *
     * @param requestFactory
     * @return
     */
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory) {
        return new RestTemplate(requestFactory);
    }

    /**
     * 優(yōu)先用 SimpleClientHttpRequestFactory
     * @return
     */
    @Primary
    @Bean
    public ClientHttpRequestFactory simpleClient() {

        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();

        //單位為ms
        factory.setReadTimeout(5000);
        //單位為ms
        factory.setConnectTimeout(5000);

        return factory;
    }


    @Bean
    public ClientHttpRequestFactory okhttpClient() {
        OkHttp3ClientHttpRequestFactory factory = new OkHttp3ClientHttpRequestFactory();
        //單位為ms
        factory.setReadTimeout(5000);
        //單位為ms
        factory.setConnectTimeout(5000);

        return factory;
    }

}

使用 restTemplate 進(jìn)行 get,post 請(qǐng)求

 @Resource
 private RestTemplate restTemplate;

    @GetMapping("/test-restTemplate")
    public String testRestTemplate() {

        /**
         * get 請(qǐng)求
         *
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)3 請(qǐng)求攜帶參數(shù) 選填
         */
        restTemplate.getForObject("http://localhost:8802/testRestGet?username=zhangsan", String.class);

        /**
         * get 請(qǐng)求
         *
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)3 請(qǐng)求攜帶參數(shù) 選填
         */
        Map<String, String> uriVariables = new HashMap<>();
        uriVariables.put("name", "zhengsan");
        restTemplate.getForObject("http://localhost:8802/testRestGet?username={name}", String.class, uriVariables);

        /**
         * get 請(qǐng)求
         *
         * getForEntity 方法 得到 返回值類(lèi)型為 ResponseEntity
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)3 請(qǐng)求攜帶參數(shù) 選填
         */
        ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8802/testRestGet?username={name}", String.class, uriVariables);

        System.out.println("獲取響應(yīng)的狀態(tài):" + responseEntity.getStatusCode());
        System.out.println("獲取響應(yīng)的數(shù)據(jù):" + responseEntity.getBody());


        /**
         * post 請(qǐng)求
         *
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 通過(guò)LinkedMultiValueMap對(duì)象封裝請(qǐng)求參數(shù)  模擬表單參數(shù),封裝在請(qǐng)求體中
         * 參數(shù)3 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)4 請(qǐng)求攜帶參數(shù) 選填
         */
        LinkedMultiValueMap<String, String> request = new LinkedMultiValueMap<>();
        request.set("username", "zhangsan");
        restTemplate.postForObject("http://localhost:8002/testRestPost", request, Map.class);


        /**
         * post 請(qǐng)求
         *
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 通過(guò)LinkedMultiValueMap對(duì)象封裝請(qǐng)求參數(shù)  模擬表單參數(shù)几苍,封裝在請(qǐng)求體中
         * 參數(shù)3 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)4 請(qǐng)求攜帶參數(shù) 選填
         */
        Map<String, String> uriVariables2 = new HashMap<>();
        uriVariables.put("address", "china");
        restTemplate.postForObject("http://localhost:8802/testRestPost?address={address}", request, Map.class, uriVariables2);


        /**
         * post 請(qǐng)求
         *
         * getForEntity 方法 得到 返回值類(lèi)型為 ResponseEntity
         * 參數(shù)1 要請(qǐng)求的地址的url  必填項(xiàng)
         * 參數(shù)2 通過(guò)LinkedMultiValueMap對(duì)象封裝請(qǐng)求參數(shù)  模擬表單參數(shù)翻屈,封裝在請(qǐng)求體中
         * 參數(shù)3 響應(yīng)數(shù)據(jù)的類(lèi)型 是String 還是 Map等 必填項(xiàng)
         * 參數(shù)4 請(qǐng)求攜帶參數(shù) 選填
         */
        ResponseEntity<String> responseEntity2 = restTemplate.postForEntity("http://localhost:8002/testRestPost", request, String.class, uriVariables2);
        System.out.println("獲取響應(yīng)的狀態(tài):" + responseEntity2.getStatusCode());
        System.out.println("獲取響應(yīng)的數(shù)據(jù):" + responseEntity2.getBody());


        /**
         * post 請(qǐng)求
         *
         * 登錄or注冊(cè)都是post請(qǐng)求,而這些操作完成之后呢妻坝?大部分都是跳轉(zhuǎn)到別的頁(yè)面去了伸眶,這種場(chǎng)景下,就可以使用 postForLocation 了刽宪,提交數(shù)據(jù)厘贼,并獲取返回的URI
         * 響應(yīng)參數(shù)要跳轉(zhuǎn)的地址
         */
        //uri : "redirect:/success.html"
        URI uri = restTemplate.postForLocation("http://localhost:8802/testRestPostLocation", request);
        System.out.println("postForLocation請(qǐng)求到的地址為:" + uri);


        return null;
    }

設(shè)置請(qǐng)求header

方法1 先配置http的request攔截器

public class RestTemplateIntercepor implements ClientHttpRequestInterceptor {

    @Override
    public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution) throws IOException {

      HttpHeaders headers =  httpRequest.getHeaders();

        headers.add(HttpHeaders.USER_AGENT,
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");

        //add自己的header

        return execution.execute(httpRequest, body);
    }
}

設(shè)置 Interceptors


 restTemplate.setInterceptors(Collections.singletonList(new RestTemplateIntercepor()));

        restTemplate.getForObject("http://localhost:8802/testRestGet?username=zhangsan", String.class);

方法2

        //1. 設(shè)置請(qǐng)求頭參數(shù)
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add(HttpHeaders.USER_AGENT,
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");

        //2. 模擬表單參數(shù) 請(qǐng)求體攜帶參數(shù)
        LinkedMultiValueMap<String, String> requestBody = new LinkedMultiValueMap<>();
        requestBody.add("username", "zhangsan");

        //3. 封裝HttpEntity對(duì)象
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity<MultiValueMap>(requestBody, requestHeaders);

        //4.獲取 restTemplate
        RestTemplate restTemplate2 = new RestTemplate();


        //5.請(qǐng)求url
        ResponseEntity<String> responseEntity =restTemplate2.postForEntity("http://localhost:8802/testRestPost",requestEntity,String.class);
        System.out.println("獲取響應(yīng)的狀態(tài):" + responseEntity.getStatusCode());
        System.out.println("獲取響應(yīng)的數(shù)據(jù):" + responseEntity.getBody());

http 協(xié)議參考文檔:
http2協(xié)議(英文)
w3cschool介紹

restTemplate參考:
HttpClient、RestTemplate和Feign相關(guān)知識(shí)
使用RestTemplate和Feign進(jìn)行微服務(wù)通信
restTemplate使用指南
基于springboot的RestTemplate圣拄、okhttp和HttpClient對(duì)比

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嘴秸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子庇谆,更是在濱河造成了極大的恐慌岳掐,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饭耳,死亡現(xiàn)場(chǎng)離奇詭異串述,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)寞肖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)剖煌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)材鹦,“玉大人,你說(shuō)我怎么就攤上這事耕姊⊥疤疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵茉兰,是天一觀的道長(zhǎng)尤泽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)规脸,這世上最難降的妖魔是什么坯约? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任摊腋,我火速辦了婚禮蹂空,結(jié)果婚禮上曹锨,老公的妹妹穿的比我還像新娘袜炕。我一直安慰自己,他們只是感情好贡翘,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蝇庭。 她就那樣靜靜地躺著吼旧,像睡著了一般梨与。 火紅的嫁衣襯著肌膚如雪堕花。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,590評(píng)論 1 305
  • 那天粥鞋,我揣著相機(jī)與錄音缘挽,去河邊找鬼。 笑死呻粹,一個(gè)胖子當(dāng)著我的面吹牛壕曼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播等浊,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼窝稿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凿掂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤纹蝴,失蹤者是張志新(化名)和其女友劉穎庄萎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體塘安,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糠涛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兼犯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忍捡。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡集漾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砸脊,到底是詐尸還是另有隱情具篇,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布凌埂,位于F島的核電站驱显,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞳抓。R本人自食惡果不足惜埃疫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孩哑。 院中可真熱鬧栓霜,春花似錦、人聲如沸横蜒。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)愁铺。三九已至鹰霍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茵乱,已是汗流浹背茂洒。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瓶竭,地道東北人督勺。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像斤贰,于是被迫代替她去往敵國(guó)和親智哀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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