REST (REpresentational State Transfer)臭猜,直譯:表現(xiàn)層狀態(tài)轉(zhuǎn)移瓶珊。這個(gè)中文直譯經(jīng)常出現(xiàn)在很多文章中夹界。尼瑪戈次,誰(shuí)聽(tīng)得懂“表現(xiàn)層狀態(tài)轉(zhuǎn)移”轩勘,這是人話嗎?
那就逐個(gè)單詞來(lái)理解REST名稱(chēng)
REST -- REpresentational State Transfer
首先朝扼,之所以晦澀是因?yàn)榍懊娴闹髡Z(yǔ)被去掉了赃阀,全稱(chēng)是 Resource Representational State Transfer,通俗來(lái)講就是:資源在網(wǎng)絡(luò)中以某種表現(xiàn)形式進(jìn)行狀態(tài)轉(zhuǎn)移擎颖。
分解開(kāi)來(lái):
Resource:資源榛斯,即數(shù)據(jù)(前面說(shuō)過(guò)網(wǎng)絡(luò)的核心)。比如 newsfeed搂捧,friends等驮俗;
Representational:某種表現(xiàn)形式,比如用JSON允跑,XML王凑,JPEG等;
State Transfer:狀態(tài)變化聋丝。通過(guò)HTTP動(dòng)詞實(shí)現(xiàn)索烹。
為什么要用RESTful結(jié)構(gòu)呢?
大家都知道“古代”網(wǎng)頁(yè)是前端后端融在一起的弱睦,比如之前的PHP百姓,JSP等,在之前的桌面時(shí)代况木,前后端融合在一起沒(méi)啥問(wèn)題垒拢,但是近年來(lái)移動(dòng)互聯(lián)網(wǎng)的發(fā)展旬迹,各種類(lèi)型的Client層出不窮,RESTful可以通過(guò)一套統(tǒng)一的接口為Web求类、iOS奔垦、Android、小程序等提供接口API服務(wù)尸疆。另外對(duì)于廣大平臺(tái)來(lái)說(shuō)椿猎,比如Facebook platform,微博開(kāi)放平臺(tái)仓技,微信公共平臺(tái)等鸵贬,它們不需要有顯式的前端,只需要一套提供服務(wù)的接口脖捻,于是RESTful的API更是它們最好的選擇。
從原理角度來(lái)分析
根據(jù)Richardson Maturity Model(理查德森成熟度模型), REST架構(gòu)的成熟度有4個(gè)等級(jí):
Level 0 - 面向前臺(tái)
我們?cè)诳Х鹊晗蚯芭_(tái)點(diǎn)了一杯拿鐵咖啡兆衅,這個(gè)過(guò)程可以用這段文字來(lái)描述:
{
"addOrder": {
"orderName": "latte"
}
}
我們通過(guò)這段文字告訴前臺(tái)地沮,新增一筆訂單,訂單是一杯拿鐵咖啡羡亩,接著摩疑,前臺(tái)給我們返回這么一串回復(fù):
{
"orderId": "123456"
}
假設(shè)我們有一張會(huì)員卡,我們想查詢一下這張會(huì)員卡的余額畏铆,這時(shí)候要向前臺(tái)發(fā)起另一個(gè)詢問(wèn):
{
"queryBalance": {
"cardId": "447031335"
}
}
查詢卡號(hào)為447031335的卡的余額雷袋,查詢的結(jié)果返回來(lái)了:
{
"balance": "0"
}
沒(méi)錢(qián)……哈哈哈,沒(méi)錢(qián)辞居,現(xiàn)在我們要跟前臺(tái)說(shuō)楷怒,這杯咖啡不要了:
{
"deleteOrder": {
"orderId": "123456"
}
}
Level 1 - 面向資源
現(xiàn)在這家咖啡店越做越大,來(lái)喝咖啡的人越來(lái)越多瓦灶,單靠前臺(tái)顯然是不行的鸠删,店主決定進(jìn)行分工,每個(gè)資源都有專(zhuān)人負(fù)責(zé)贼陶,我們可以直接面向資源操作刃泡。
比如還是下單,請(qǐng)求的內(nèi)容不變碉怔,但是我們多了一條消息:
/orders
{
"addOrder": {
"orderName": "latte"
}
}
多了一個(gè)斜杠和orders烘贴,這是什么意思?
這個(gè)表示我們這個(gè)請(qǐng)求是發(fā)給哪個(gè)資源的撮胧,訂單是一種資源桨踪,我們可以理解為是咖啡廳專(zhuān)門(mén)管理訂單的人,他可以幫我們處理所有有關(guān)訂單的操作趴樱,包括新增訂單馒闷、修改訂單酪捡、取消訂單等操作。
接著還是會(huì)返回訂單的編號(hào)給我們:
{
"orderId": "123456"
}
下面纳账,我們還是要查詢會(huì)員卡余額逛薇,這次請(qǐng)求的資源變成了cards:
/cards
{
"queryBalance": {
"cardId": "447031335"
}
}
接下來(lái)是取消訂單:
/orders
{
"deleteOrder": {
"orderId": "123456"
}
}
Level 2 - 打上標(biāo)簽
接下來(lái),店主還想繼續(xù)優(yōu)化他的咖啡廳的服務(wù)流程疏虫,他發(fā)現(xiàn)負(fù)責(zé)處理訂單的員工永罚,每次都要去訂單內(nèi)容里面看是新增訂單還是刪除訂單,還是其他的什么操作卧秘,十分不方便呢袱,于是規(guī)定,所有新增資源的請(qǐng)求翅敌,都在請(qǐng)求上面寫(xiě)上大大的“POST”羞福,表示這是一筆新增資源的請(qǐng)求。
其他種類(lèi)的請(qǐng)求蚯涮,比如查詢類(lèi)的治专,用‘GET’表示,刪除類(lèi)的遭顶,用‘DELETE’表示张峰,修改用PATCH表示。
來(lái)棒旗,我們?cè)賮?lái)重復(fù)上面那個(gè)過(guò)程喘批,來(lái)一杯拿鐵:
POST /orders
{
"orderName": "latte"
}
請(qǐng)求的內(nèi)容簡(jiǎn)潔多啦,不用告訴店員是addOrder铣揉,看到POST就知道是新增饶深,返回的內(nèi)容還是一樣:
{
"orderId": "123456"
}
接著是查詢會(huì)員卡余額,這次也簡(jiǎn)化了很多:
GET /cards
{
"cardId": "447031335"
}
這個(gè)請(qǐng)求我們還可以進(jìn)一步優(yōu)化為這樣:
GET /cards/447031335
直接把要查詢的卡號(hào)寫(xiě)在后面了老速。
沒(méi)錯(cuò)粥喜,接著,取消訂單:
DELETE /orders/123456
Level 3 - 完美服務(wù)
忽然有一天橘券,有個(gè)顧客抱怨說(shuō)额湘,他買(mǎi)了咖啡后,不知道要怎么取消訂單旁舰,咖啡廳一個(gè)店員回了一句锋华,你不會(huì)看我們的宣傳單嗎,上面不寫(xiě)著:
DELETE /orders/{orderId}
顧客反問(wèn)道箭窜,誰(shuí)會(huì)去看那個(gè)啊毯焕,店員不服,又說(shuō)到,你瞎了啊你……后面兩人吵著吵著還打了起來(lái)…
噗纳猫,真是悲劇…
有了這次教訓(xùn)婆咸,店長(zhǎng)決定,顧客下了單之后芜辕,不僅給他們返回訂單的編號(hào)尚骄,還給顧客返回所有可以對(duì)這個(gè)訂單做的操作,比如告訴用戶如何刪除訂單∏中現(xiàn)在倔丈,我們還是發(fā)出請(qǐng)求,請(qǐng)求內(nèi)容和上一次一樣:
POST /orders
{
"orderName": "latte"
}
但是這次返回時(shí)多了些內(nèi)容:
{
"orderId": "123456",
"link": {
"rel": "cancel",
"url": "/order/123456"
}
}
這次返回時(shí)多了一項(xiàng)link信息状蜗,里面包含了一個(gè)rel屬性和url屬性需五,rel是relationship的意思,這里的關(guān)系是cancel轧坎,url則告訴你如何執(zhí)行這個(gè)cancel操作宏邮,接著你就可以這樣子來(lái)取消訂單啦:
DELETE /orders/123456
哈哈,這服務(wù)真是貼心缸血,以后再也不用擔(dān)心店員和顧客打起來(lái)了蜀铲。
Level 3的Restful API,給使用者帶來(lái)了很大的便利属百,使用者只需要知道如何獲取資源的入口,之后的每個(gè)URI都可以通過(guò)請(qǐng)求獲得变姨,無(wú)法獲得就說(shuō)明無(wú)法執(zhí)行那個(gè)請(qǐng)求田轧。
現(xiàn)在絕大多數(shù)的RESTful接口都做到了Level2的層次舔糖,做到Level3的比較少。當(dāng)然,這個(gè)模型并不是一種規(guī)范辆飘,只是用來(lái)理解Restful的工具。所以湃望,做到了Level2驶赏,也就是面向資源和使用http動(dòng)詞,就已經(jīng)很Restful了爷辱。
Levels的意義
Level 1 解釋了如何通過(guò)分治法(Divide and Conquer)來(lái)處理復(fù)雜問(wèn)題录豺,將一個(gè)大型的服務(wù)端點(diǎn)(Service Endpoint)分解成多個(gè)資源。
Level 2 引入了一套標(biāo)準(zhǔn)的動(dòng)詞饭弓,用來(lái)以相同的方式應(yīng)對(duì)類(lèi)似的場(chǎng)景双饥,移除不要的變化。
Level 3 引入了可發(fā)現(xiàn)性(Discoverability)弟断,它可以使協(xié)議擁有自我描述(Self-documenting)的能力咏花。
這一模型幫助我們思考我們想要提供的HTTP服務(wù)是何種類(lèi)型的,同時(shí)也勾勒出人們和它進(jìn)行交互時(shí)的期望阀趴。
從應(yīng)用角度來(lái)分析
? REST描述的是在網(wǎng)絡(luò)中client和server的一種交互形式昏翰;REST本身不實(shí)用苍匆,實(shí)用的是如何設(shè)計(jì) RESTful API(REST風(fēng)格的網(wǎng)絡(luò)接口);
? Server提供的RESTful API中棚菊,URL中只使用名詞來(lái)指定資源浸踩,原則上不使用動(dòng)詞∏现辏“資源”是REST架構(gòu)或者說(shuō)整個(gè)網(wǎng)絡(luò)處理的核心民轴,
URL定位資源,用HTTP動(dòng)詞(GET/POST/DELETE/PATCH)來(lái)描述操作球订,
- 看url就知道要什么
- 看http method就知道干什么
- 看http status code就知道結(jié)果如何
比如:
http://api.qc.com/v1/newsfeed: 獲取某人的新鮮;
http://api.qc.com/v1/friends: 獲取某人的好友列表;
http://api.qc.com/v1/profile: 獲取某人的詳細(xì)信息;
? 用HTTP協(xié)議里的動(dòng)詞來(lái)實(shí)現(xiàn)資源的添加后裸、修改、刪除等操作冒滩。即通過(guò)HTTP動(dòng)詞來(lái)實(shí)現(xiàn)資源的狀態(tài)轉(zhuǎn)移:
- GET 用來(lái)獲取資源微驶,
- POST 用來(lái)新建資源(也可以用于更新資源),
- PUT 用來(lái)更新資源开睡,
- DELETE 用來(lái)刪除資源因苹。
比如:
DELETE http://api.qc.com/v1/friends: 刪除某人的好友 (在http parameter指定好友id)
POST http://api.qc.com/v1/friends: 添加好友
UPDATE http://api.qc.com/v1/profile: 更新個(gè)人資料
? Server和Client之間傳遞某資源的一個(gè)表現(xiàn)形式,比如用JSON篇恒,XML傳輸文本扶檐,或者用JPG,WebP傳輸圖片等胁艰。當(dāng)然還可以壓縮HTTP傳輸時(shí)的數(shù)據(jù)(on-wire data compression);
? 用 HTTP Status Code傳遞Server的狀態(tài)信息款筑。比如最常用的 200 表示成功,500 表示Server內(nèi)部錯(cuò)誤等腾么。
好了奈梳,理解了RESTful的概念,究竟如何應(yīng)用解虱,這是個(gè)問(wèn)題攘须。根據(jù)項(xiàng)目的需求不同,我們的API設(shè)計(jì)規(guī)范也存在差別殴泰,完全看自身理解于宙,滿足自身需求,大的理念不變艰匙,根據(jù)需求制定項(xiàng)目的API規(guī)范就是好的RESTful限煞。