RESTful 架構(gòu) (表現(xiàn)層狀態(tài)轉(zhuǎn)移)

理解由來

概念是 Roy Thomas Fielding在他2000年的博士論文中提出的偏螺。他參與制定了 HTTP 1.0 和 HTTP 1.1 協(xié)議。

他希望能基于網(wǎng)絡(luò)現(xiàn)有的協(xié)議基礎(chǔ)上創(chuàng)建一個(gè)功能強(qiáng)大,性能游戲,適宜通信的架構(gòu)。

概念

客戶端 - 服務(wù)器分離(Client - Server)

如含義一樣朋沮,將從邏輯上將業(yè)務(wù)實(shí)現(xiàn)拆分為客戶端與服務(wù)端實(shí)現(xiàn)。

通過分離設(shè)計(jì)缀壤,能簡化兩邊的設(shè)計(jì)復(fù)雜度樊拓,提高其可擴(kuò)展性纠亚。

資源(Resources)

資源是 RESTful 的主體,主要指代互聯(lián)網(wǎng)上的一個(gè)實(shí)體筋夏,可以是一段文本蒂胞、一張圖片、一首歌曲条篷、一種服務(wù)啤誊,總之就是一個(gè)具體的實(shí)在。資源通過 URI 來唯一標(biāo)識(shí)拥娄。

表現(xiàn)層(Representation)

資源的信息載體形式,叫做表現(xiàn)層瞳筏。他可以是文本稚瘾、XML、JSON 或者是一個(gè)二進(jìn)制文件姚炕。它的具體表現(xiàn)形式摊欠,應(yīng)該在HTTP請(qǐng)求的頭信息中用Accept和Content-Type字段指定,這兩個(gè)字段才是對(duì)"表現(xiàn)層"的描述柱宦。

狀態(tài)轉(zhuǎn)化(State Transfer)

互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議些椒,是一個(gè)無狀態(tài)協(xié)議。這意味著掸刊,所有的狀態(tài)都保存在服務(wù)器端免糕。因此,如果客戶端想要操作服務(wù)器忧侧,必須通過某種手段石窑,讓服務(wù)器端發(fā)生"狀態(tài)轉(zhuǎn)化"(State Transfer)。而這種轉(zhuǎn)化是建立在表現(xiàn)層之上的蚓炬,所以就是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"松逊。

在 HTTP 中,我們一般通過四種 HTTP 動(dòng)詞(verb)來對(duì)應(yīng)資源的變化:GET用來獲取資源肯夏,POST用來新建資源(也可以用于更新資源)经宏,PUT用來更新資源,DELETE用來刪除資源驯击。

相應(yīng)的狀態(tài)的交互應(yīng)當(dāng)是無狀態(tài)的(ServerLess)這是 HTTP 的特性所決定的烁兰,要求每次請(qǐng)求包含服務(wù)器需要的所有信息,這樣可以很好的確保每一次變化的可預(yù)測性余耽,進(jìn)而提高可靠性缚柏,也能增進(jìn)可擴(kuò)展性。

綜述

綜合上面的解釋碟贾,我們總結(jié)一下什么是RESTful架構(gòu):

(1)每一個(gè)URI代表一種資源币喧;

(2)客戶端和服務(wù)器之間轨域,傳遞這種資源的某種表現(xiàn)層;

(3)客戶端通過四個(gè)HTTP動(dòng)詞杀餐,對(duì)服務(wù)器端資源進(jìn)行操作干发,實(shí)現(xiàn)"表現(xiàn)層狀態(tài)轉(zhuǎn)化"。

HTTP 與 RESTful

HTTP 請(qǐng)求是互聯(lián)網(wǎng)架構(gòu)中重要的一環(huán)史翘,其在 TCP 連接的基礎(chǔ)上枉长,實(shí)現(xiàn)了語義化,緩存機(jī)制琼讽,無狀態(tài)等等特性必峰。在互聯(lián)網(wǎng)上也有不錯(cuò)的性能,REST 常常會(huì)基于 HTTP 協(xié)議的基礎(chǔ)上實(shí)現(xiàn)其核心概念钻蹬。

論文中對(duì) HTTP 與 REST 相適宜的論述提及了幾點(diǎn):

  1. 可擴(kuò)展性:主要是協(xié)議的 method吼蚁,返回狀態(tài)碼,協(xié)議向下兼容性
  2. 自我信息描述:主要是從 URI 能準(zhǔn)確定義資源问欠,Content-type HTTP 頭能準(zhǔn)確定義表現(xiàn)層肝匆,還有相關(guān)語義化的 HTTP 頭。
  3. 性能:主要從 HTTP 高于網(wǎng)絡(luò)層顺献,在實(shí)現(xiàn)上能復(fù)用 TCP 連接旗国,減少 TCP 建立與銷毀的時(shí)間成本。還有就是 HTTP 其容易緩存的特性注整。

這里是論文中對(duì) HTTP Code 來表現(xiàn)業(yè)務(wù)相應(yīng)狀態(tài)的相關(guān)表述:

論文中關(guān)于 HTTP 狀態(tài)碼與 RESTful 適配的論述

Matin Fowler 關(guān)于 RESTful 的成熟度模型

原文: https://martinfowler.com/articles/richardsonMaturityModel.html

他講這個(gè)模型層次分為四級(jí)能曾,大概如下所示:

RESTful 成熟度模型

Level 0

利用 HTTP 協(xié)議做數(shù)據(jù)交換,所有的參數(shù)描述通過 url 或者 POST body 形式通知服務(wù)器设捐,返回相應(yīng)的數(shù)據(jù)借浊,此級(jí)別通常都是基于 。實(shí)質(zhì)上就是基于 HTTP 的 RPC(遠(yuǎn)程過程調(diào)用)萝招,具體交付的細(xì)節(jié)完全由相關(guān)規(guī)范或團(tuán)隊(duì)內(nèi)部約定解決蚂斤。

根據(jù)理解設(shè)計(jì)了一份請(qǐng)求交互:

POST /apiService

{
    "action": "bookMeeting",
    "roomID": "Roma",
    "guestIDs": ["Roy", "Tom"],
    "from": "201805221400",
    "to": "201805221500"
}

------- Response

{
    "status": "succuess",
    "guestIDs": ["Roy", "Tom"],
    "meetingID": "201805221400-201805221500-Roma"
}

Level 1

將 API 按照 RESTful 中資源的方式進(jìn)行劃分,初步有了自我描述(self description)的特性了槐沼,客戶端可以對(duì)相關(guān)的資源進(jìn)行更加細(xì)致的操作曙蒸。

根據(jù)理解設(shè)計(jì)了一份請(qǐng)求交互:

POST /apiService/room/Roma

{
    "action": "bookMeeting",
    "guestIDs": ["Roy", "Tom"],
    "from": "201805221400",
    "to": "201805221500"
}

------- Response

{
    "status": "succuess",
    "guestIDs": ["Roy", "Tom"],
    "meetingID": "201805221400-201805221500-Roma"
}

Level 2

這個(gè)級(jí)別有更加進(jìn)一步的利用了 HTTP 的特性,增加了對(duì) HTTP verb (比如 GET 表示查詢岗钩、POST 表示創(chuàng)建纽窟、PUT 表示修改、DELETE 表示 等等)的運(yùn)用兼吓,并且運(yùn)用原有的 HTTP response status 來表征業(yè)務(wù)上請(qǐng)求的成功與失敗臂港,一般項(xiàng)目常見的 RESTful 運(yùn)用基本都接近這個(gè)級(jí)別。

這個(gè)請(qǐng)求基本就和我們平時(shí)使用的 RESTful api 很接近了:

POST /apiService/room/Roma

{
    "guestIDs": ["Roy", "Tom"],
    "from": "201805221400",
    "to": "201805221500"
}

------- Response

status: 201

{
    "guestIDs": ["Roy", "Tom"],
    "meetingID": "201805221400-201805221500-Roma"
}

Level 3

這個(gè)基本也稱作 HATEOAS (Hypertext As The Engine Of Application State),這個(gè)級(jí)別是 RESTful 最復(fù)雜的實(shí)現(xiàn)审孽,這個(gè)級(jí)別最理想的情況是县袱,不需要特別復(fù)雜 API 文檔進(jìn)行描述的,這里的 API 設(shè)計(jì)最大化的實(shí)現(xiàn)了 RESTful 的自我描述特性佑力。這種方案雖然引入很大的復(fù)雜性式散,但是最大限度的將 API 設(shè)計(jì)變得配置化了,所有 API 設(shè)計(jì)將會(huì)基于更加抽象的工作流設(shè)計(jì)了打颤,稍后再做解釋:

本階段的相關(guān)請(qǐng)求模型大概是這樣的:

GET /apiService/room

---- Response
{
    roomList: [
        {
            meetingID: "Roma",
            __link: [
                {
                    method: "POST",
                    url: "/apiService/room/Roma",
                    parameters: {
                        guestIDs: "[guestID]",
                        from: "timestamp",
                        to: "timestamp"
                    }
                }
            ]
        },
        ...
    ]
}


------------


POST /apiService/room/Roma

{
    "guestIDs": ["Roy", "Tom"],
    "from": "201805221400",
    "to": "201805221500"
}

------- Response

status: 201

{
    "meetingID": "201805221400-201805221500-Roma"
    _links: [
        {
            url: '/apiService/meeting/201805221400-201805221500-Roma',
            methos: 'GET'
        },
        ...
    ]
}

可以看出暴拄,從查詢到最終結(jié)果,都是由第一個(gè) api 的返回的資源列表和操作項(xiàng)编饺,引導(dǎo)向后面的操作乖篷,這樣,后端在設(shè)計(jì) API 的時(shí)候透且,需要考慮從一條業(yè)務(wù) workflow 的角度去設(shè)計(jì)那伐。這樣只要整個(gè)流程不變,局部的數(shù)據(jù)變化石蔗,只需要修改后端的相關(guān)配置即可,這樣業(yè)務(wù)可以很大程度的配置化畅形。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末养距,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子日熬,更是在濱河造成了極大的恐慌棍厌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竖席,死亡現(xiàn)場離奇詭異耘纱,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)毕荐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門束析,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人憎亚,你說我怎么就攤上這事员寇。” “怎么了第美?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵蝶锋,是天一觀的道長。 經(jīng)常有香客問我什往,道長扳缕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮躯舔,結(jié)果婚禮上驴剔,老公的妹妹穿的比我還像新娘。我一直安慰自己庸毫,他們只是感情好仔拟,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著飒赃,像睡著了一般利花。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上载佳,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天炒事,我揣著相機(jī)與錄音,去河邊找鬼蔫慧。 笑死挠乳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的姑躲。 我是一名探鬼主播睡扬,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼黍析!你這毒婦竟也來了卖怜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤阐枣,失蹤者是張志新(化名)和其女友劉穎马靠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔼两,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡甩鳄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了额划。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妙啃。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俊戳,靈堂內(nèi)的尸體忽然破棺而出彬祖,到底是詐尸還是另有隱情,我是刑警寧澤品抽,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布储笑,位于F島的核電站,受9級(jí)特大地震影響圆恤,放射性物質(zhì)發(fā)生泄漏突倍。R本人自食惡果不足惜腔稀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望羽历。 院中可真熱鬧焊虏,春花似錦、人聲如沸秕磷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澎嚣。三九已至疏尿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間易桃,已是汗流浹背褥琐。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晤郑,地道東北人敌呈。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像造寝,于是被迫代替她去往敵國和親磕洪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理诫龙,服務(wù)發(fā)現(xiàn)褐鸥,斷路器,智...
    卡卡羅2017閱讀 134,696評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,277評(píng)論 25 707
  • 不知道換了個(gè)畫風(fēng)大家還認(rèn)得出包哥不 他強(qiáng)烈要求以后就用這個(gè) “帥得一嗶”的畫風(fēng) 我當(dāng)然不會(huì)滿足他啊 今天也是包哥基...
    素菜包閱讀 615評(píng)論 8 6
  • 如果再也見不到你赐稽,那么祝你早安,午安浑侥,晚安姊舵。 公寓門口的廣式早點(diǎn)以后不來了,難過寓落±ǘ。回想起它帶給我的滿足,感謝每一段...
    GEMLin閱讀 249評(píng)論 0 0
  • 感謝電腦時(shí)代伶选,到點(diǎn)自動(dòng)關(guān)賬史飞,所以有了元旦的休息日,感謝這個(gè)偉大的時(shí)代仰税。 假期里幾場同學(xué)聚會(huì)我都沒有參加构资,第一和大家...
    mimi播報(bào)閱讀 397評(píng)論 1 7