Spring Boot使用Spring RestTemplate詳解

1乒融、什么是REST格仲?

REST(Representational State Transfer)是Roy Fielding 提出的一個描述互聯(lián)系統(tǒng)架構(gòu)風(fēng)格的名詞二汛。REST定義了一組體系架構(gòu)原則铸董,您可以根據(jù)這些原則設(shè)計以系統(tǒng)資源為中心的Web 服務(wù)灭贷,包括使用不同語言編寫的客戶端如何通過 HTTP處理和傳輸資源狀態(tài)危队。

為什么稱為 REST聪建?Web本質(zhì)上由各種各樣的資源組成,資源由URI 唯一標(biāo)識茫陆。瀏覽器(或者任何其它類似于瀏覽器的應(yīng)用程序)將展示出該資源的一種表現(xiàn)方式金麸,或者一種表現(xiàn)狀態(tài)。如果用戶在該頁面中定向到指向其它資源的鏈接簿盅,則將訪問該資源挥下,并表現(xiàn)出它的狀態(tài)。這意味著客戶端應(yīng)用程序隨著每個資源表現(xiàn)狀態(tài)的不同而發(fā)生狀態(tài)轉(zhuǎn)移桨醋,也即所謂REST棚瘟。

附:REST定義RESTSOAP的比較

2喜最、REST成熟度的四個層次

  • 第一個層次(Level0)的Web 服務(wù)只是使用 HTTP 作為傳輸方式偎蘸,實(shí)際上只是遠(yuǎn)程方法調(diào)用(RPC)的一種具體形 式。SOAP和 XML-RPC都屬于此類瞬内。

  • 第二個層次(Level1)的Web 服務(wù)引入了資源的概念迷雪。每個資源有對應(yīng)的標(biāo)識符和表達(dá)。

  • 第三個層次(Level2)的Web 服務(wù)使用不同的 HTTP 方法來進(jìn)行不同的操作虫蝶,并且使用HTTP 狀態(tài)碼來表示不同的結(jié)果章咧。如 HTTPGET 方法來獲取資源,HTTPDELETE 方法來刪除資源能真。

  • 第四個層次(Level3)的Web 服務(wù)使用 HATEOAS赁严。在資源的表達(dá)中包含了鏈接信息》垲恚客戶端可以根據(jù)鏈接來發(fā)現(xiàn)可以執(zhí)行的動作疼约。

其中第三個層次建立了創(chuàng)建、讀取秦躯、更新和刪除(create,read, update, and delete忆谓,CRUD)操作與 HTTP方法之間的一對一映射。根據(jù)此映射:

  • 若要在服務(wù)器上創(chuàng)建資源踱承,應(yīng)該使用POST 方法倡缠。

  • 若要檢索某個資源哨免,應(yīng)該使用GET 方法。

  • 若要更改資源狀態(tài)或?qū)ζ溥M(jìn)行更新昙沦,應(yīng)該使用PUT 方法琢唾。

  • 若要刪除某個資源,應(yīng)該使用DELETE 方法盾饮。

3采桃、HTTP請求的方法

  • GET:通過請求URI得到資源
  • POST:用于添加新的內(nèi)容
  • PUT:用于修改某個內(nèi)容,若不存在則添加
  • DELETE:刪除某個內(nèi)容
  • OPTIONS :詢問可以執(zhí)行哪些方法
  • HEAD :類似于GET, 但是不返回body信息丘损,用于檢查對象是否存在普办,以及得到對象的元數(shù)據(jù)
  • CONNECT :用于代理進(jìn)行傳輸,如使用SSL
  • TRACE:用于遠(yuǎn)程診斷服務(wù)器

4徘钥、HTTP請求的狀態(tài)碼

  • 成功Successful 2xx:此類狀態(tài)碼標(biāo)識客戶端的請求被成功接收衔蹲、理解并接受。常見如200(OK)呈础、204(NoContent)舆驶。
  • 重定向Redirection 3xx:這個類別的狀態(tài)碼標(biāo)識用戶代理要做出進(jìn)一步的動作來完成請求。常見如301(MovedPermanently)而钞、302(MovedTemprarily)沙廉。
  • 客戶端錯誤Client Error 4xx:4xx類別的狀態(tài)碼是當(dāng)客戶端出錯的時候使用的。常見如400(BadRequest)臼节、401(Unauthorized)撬陵、403(Forbidden)、404(NotFound)网缝。
  • 服務(wù)器錯誤Server Error 5xx:響應(yīng)狀態(tài)碼以5開頭表示服務(wù)器知道自己出錯或者沒有能力執(zhí)行請求袱结。常見如500(InternalServer Error)、502(BadGateway)途凫、504(GatewayTimeout)。

附HTTP1.1的標(biāo)準(zhǔn)簡介:http://blog.chinaunix.net/uid-9188830-id-2007021.html

5溢吻、RestTemplate

5.1 簡介

Spring's central class for synchronous client-side HTTP access. It simplifies communication with HTTPservers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs(with possible template variables) and extract results.

簡單說就是:簡化了發(fā)起HTTP請求以及處理響應(yīng)的過程维费,并且支持REST。為什么說簡化了呢促王?

來看兩種實(shí)現(xiàn)方式

(1)使用java.net包下的URLConnection建立連接
        String result= "";  
        BufferedReader in = null;  
        try {  
            String urlNameString= url +"?" + param;  
            URL realUrl= new URL(urlNameString);  
            // 打開和URL之間的連接  
            URLConnection connection = realUrl.openConnection();  
            // 設(shè)置通用的請求屬性  
            connection.setRequestProperty("accept","*/*");  
            connection.setRequestProperty("connection","Keep-Alive");  
            connection.setRequestProperty("user-agent",  
                    "Mozilla/4.0(compatible; MSIE 6.0; Windows NT 5.1;SV1)");  
            // 建立實(shí)際的連接  
            connection.connect();  
            // 獲取所有響應(yīng)頭字段  
            Map<String,List<String>> map = connection.getHeaderFields();  
            // 遍歷所有的響應(yīng)頭字段  
            for(String key : map.keySet()) {  
                System.out.println(key+ "--->" + map.get(key));  
            }  
            // 定義 BufferedReader輸入流來讀取URL的響應(yīng)  
            in =new BufferedReader(new InputStreamReader(  
                    connection.getInputStream()));  
            String line;  
            while ((line = in.readLine())!= null) {  
                result += line;  
            }  
        } catch (Exception e) {  
            …  
        }  
        // 使用finally塊來關(guān)閉輸入流  
        finally{  
         // 關(guān)閉流  
        }  
(2)使用RestTempalte
ResponseEntity<SsoUrlPrm> result = restTemplate.getForEntity(requestPathUrl,SsoUrlPrm.class);  

5.2 對外開放的接口

(1)
DELETE delete
GET getForObject
getForEntity
HEAD headForHeaders
OPTIONS optionsForAllow
POST postForLocation
postForObject
PUT put
any exchange
execute
(2)每一個小類又分三種方法犀盟,這三種方法有什么區(qū)別?
  • 第一種和第二種的首個參數(shù)都是用String表示一個URI蝇狼。但它們的最后一個參數(shù)分別是Object[]和Map

  • 第三種的首個參數(shù)使用java.net.URI表示一個URI阅畴。且只有兩個參數(shù)。這是因為迅耘,String類型的URI支持占位符贱枣。

比如:restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}",String.class,"42", "21");

那么最終訪問的URI為:http://example.com/hotels/42/bookings/21

但是String有一個小缺陷:String形式的URI會被URL編碼兩次(URL encode請自行百度)监署,這就要求服務(wù)器在獲取URI中的參數(shù)時主動進(jìn)行一次解碼,但如果服務(wù)的提供者不這么做呢纽哥?

這時就需要使用不會使用任何編碼的java.net.URI

PS:參數(shù)Class<T> responseType定義了返回數(shù)據(jù)的類型钠乏。

(3)Exchange

與其它接口的不同:

允許調(diào)用者指定HTTP請求的方法(GET,POST,PUT等)

可以在請求中增加body以及頭信息,其內(nèi)容通過參數(shù)HttpEntity<?>requestEntity描述

exchange支持含參數(shù)的類型(即泛型類)作為返回類型春塌,該特性通過ParameterizedTypeReference<T>responseType描述晓避。比如:

List<String> a = new ArrayList<String>();   
System.out.println(a.getClass());   
System.out.println(a.getClass().getGenericSuperclass());   
ParameterizedTypeReference pt = new ParameterizedTypeReference<ArrayList<String>>() {};   
System.out.println(pt.getType());  

得到的結(jié)果是:

class java.util.ArrayList  
java.util.AbstractList<E>  
java.util.ArrayList<java.lang.String>  
  • 這是因為ParameterizedTypeReference<ArrayList<String>>并不根據(jù)實(shí)參而是使用getGenericSuperclass()方法獲取其父類的類型(注意這里的new有花括號,是ParameterizedTypeReference的子類)只壳,父類的類型通過java.lang.reflect.Type描述俏拱,然后通過Type的getActualTypeArguments()獲得了父類的實(shí)參類型,注意得到的Type類吼句,并不是class類锅必。
(4)excute

所有的get、post命辖、delete况毅、put、options尔艇、head尔许、exchange方法最終調(diào)用的都是excute方法。舉個栗子:

@Override  
public <T> T getForObject(String url, Class<T>  responseType, Object... urlVariables) throws RestClientException {  
    RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);  
    HttpMessageConverterExtractor<T> responseExtractor =  new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);  
    return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);  
}  

Excute方法只是將String格式的URI轉(zhuǎn)成了java.net.URI终娃,之后調(diào)用了doExecute方法味廊。整個調(diào)用過程

(5)doExcute
5.1 定義
protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,ResponseExtractor<T> responseExtractor) throws RestClientException {…}  

這里需要了解兩個類: RequestCallback &ResponseExtractor

5.2 RequestCallback

Callback interface for code that operates on a ClientHttpRequest. Allows to manipulate the request headers, and write to the request body.
簡單說:用于操作請求頭和body,在請求發(fā)出前執(zhí)行棠耕。

該接口有兩個實(shí)現(xiàn)類:

AcceptHeaderRequestCallback 只處理請求頭余佛,用于getXXX()方法
HttpEntityRequestCallback 繼承于AcceptHeaderRequestCallback可以處理請求頭和body,用于putXXX()窍荧、postXXX()和exchange()方法辉巡。
  • DELETE、HEAD蕊退、OPTIONS沒有使用這個接口郊楣。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瓤荔,隨后出現(xiàn)的幾起案子净蚤,更是在濱河造成了極大的恐慌,老刑警劉巖输硝,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件今瀑,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)橘荠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門屿附,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人砾医,你說我怎么就攤上這事拿撩。” “怎么了如蚜?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵压恒,是天一觀的道長。 經(jīng)常有香客問我错邦,道長探赫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任撬呢,我火速辦了婚禮伦吠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘魂拦。我一直安慰自己毛仪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布芯勘。 她就那樣靜靜地躺著箱靴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荷愕。 梳的紋絲不亂的頭發(fā)上衡怀,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音安疗,去河邊找鬼抛杨。 笑死,一個胖子當(dāng)著我的面吹牛荐类,可吹牛的內(nèi)容都是我干的怖现。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼玉罐,長吁一口氣:“原來是場噩夢啊……” “哼真竖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厌小,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎战秋,沒想到半個月后璧亚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年癣蟋,在試婚紗的時候發(fā)現(xiàn)自己被綠了透硝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡疯搅,死狀恐怖濒生,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幔欧,我是刑警寧澤罪治,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站礁蔗,受9級特大地震影響觉义,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浴井,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一晒骇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧磺浙,春花似錦洪囤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至呵曹,卻和暖如春款咖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奄喂。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工铐殃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人跨新。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓富腊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親域帐。 傳聞我的和親對象是個殘疾皇子赘被,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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

  • 一說到REST,我想大家的第一反應(yīng)就是“啊肖揣,就是那種前后臺通信方式民假。”但是在要求詳細(xì)講述它所提出的各個約束龙优,以及如...
    時待吾閱讀 3,433評論 0 19
  • API定義規(guī)范 本規(guī)范設(shè)計基于如下使用場景: 請求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請求頻率非常高羊异,建議使用雙通...
    有涯逐無涯閱讀 2,557評論 0 6
  • 16. Web MVC 框架 16.1 Spring Web MVC 框架介紹 Spring Web 模型-視圖-...
    此魚不得水閱讀 1,048評論 0 4
  • 組織:中國互動出版網(wǎng)(http://www.china-pub.com/) RFC文檔中文翻譯計劃(http://...
    Palomar閱讀 1,574評論 0 6
  • 敬愛的李老師,智慧的教授,親愛的家人們: 大家好野舶!我是來自長興南方眼視光中心的楊軍微易迹。今天是2019年3月...
    楊軍微閱讀 184評論 0 1