理解由來
概念是 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):
- 可擴(kuò)展性:主要是協(xié)議的 method吼蚁,返回狀態(tài)碼,協(xié)議向下兼容性
- 自我信息描述:主要是從 URI 能準(zhǔn)確定義資源问欠,Content-type HTTP 頭能準(zhǔn)確定義表現(xiàn)層肝匆,還有相關(guān)語義化的 HTTP 頭。
- 性能:主要從 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)表述:
Matin Fowler 關(guān)于 RESTful 的成熟度模型
原文: https://martinfowler.com/articles/richardsonMaturityModel.html
他講這個(gè)模型層次分為四級(jí)能曾,大概如下所示:
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ù)可以很大程度的配置化畅形。