REST架構(gòu)詳解

    1. 前言
    1. REST是什么
    • 2.1改艇、起源
    • 2.2兰粉、REST架構(gòu)的標(biāo)志
    • 2.3、超媒體(hypermedia)
    • 2.4恋昼、REST誤解]
    1. REST 架構(gòu)風(fēng)格的推導(dǎo)過程
    • 3.1. REST 所繼承的架構(gòu)風(fēng)格約束
    • 3.2. 在論文中推導(dǎo)出的 REST 架構(gòu)風(fēng)格圖示
    • 3.3. 一個(gè)基于 REST 的架構(gòu)的過程視圖(包括HTTP/1.1應(yīng)用實(shí)踐)]
    1. 為什么要用RESTful]
    • 4.1 常見的三種分布式應(yīng)用架構(gòu)風(fēng)格
    • 4.2 REST和DO對(duì)比
    • 4.3 REST與RPC對(duì)比]
    1. RESTful如何設(shè)計(jì)
    1. 各端的具體實(shí)現(xiàn)]
    1. Django REST Framework使用

1.前言

在「遠(yuǎn)古時(shí)代」前端后端是融合在一起的看靠,比如之前的PHP,JSP焰雕,ASP等等衷笋。近年來隨著移動(dòng)互聯(lián)網(wǎng)的飛速發(fā)展,各種類型的Client端層出不窮矩屁,就需要通過一套統(tǒng)一的接口分別為Web辟宗,iOS和Android乃至桌面端提供服務(wù)。另外對(duì)于廣大平臺(tái)來說吝秕,比如Facebook platform泊脐,微博開放平臺(tái),微信烁峭、QQ公共平臺(tái)等容客,它們不需要有顯式的前端,只需要一套提供服務(wù)的接口约郁,于是RESTful更是它們最好的選擇缩挑。

2.RESTful是什么

越來越多的人開始意識(shí)到,網(wǎng)站即軟件鬓梅,而且是一種新型的軟件供置。

這種"互聯(lián)網(wǎng)軟件"采用客戶端/服務(wù)器模式,建立在分布式體系上绽快,通過互聯(lián)網(wǎng)通信芥丧,具有高延時(shí)紧阔、高并發(fā)等特點(diǎn)。

網(wǎng)站開發(fā)续担,完全可以采用軟件開發(fā)的模式擅耽。但是傳統(tǒng)上,軟件和網(wǎng)絡(luò)是兩個(gè)不同的領(lǐng)域物遇,很少有交集乖仇;軟件開發(fā)主要針對(duì)單機(jī)環(huán)境,網(wǎng)絡(luò)則主要研究系統(tǒng)之間的通信询兴≌饩矗互聯(lián)網(wǎng)的興起,使得這兩個(gè)領(lǐng)域開始融合蕉朵,現(xiàn)在我們必須考慮,如何開發(fā)在互聯(lián)網(wǎng)環(huán)境中使用的軟件阳掐。

RESTful架構(gòu)始衅,就是目前最流行的一種互聯(lián)網(wǎng)軟件架構(gòu)。它結(jié)構(gòu)清晰缭保、符合標(biāo)準(zhǔn)汛闸、易于理解、擴(kuò)展方便艺骂,所以正得到越來越多網(wǎng)站的采用诸老。

需要注意的是,REST是一種設(shè)計(jì)風(fēng)格而不是標(biāo)準(zhǔn)钳恕,如果一個(gè)架構(gòu)符合REST原則别伏,我們就稱它為RESTful架構(gòu)。

2.1忧额、起源

在互聯(lián)網(wǎng)行業(yè)厘肮,實(shí)踐總是走在理論的前面。Web 發(fā)展到了 1995 年睦番,在 CGI类茂、ASP 等技術(shù)出現(xiàn)之后,沿用了多年托嚣、主要面向靜態(tài)文檔的 HTTP/1.0 協(xié)議已經(jīng)無法滿足 Web 應(yīng)用的開發(fā)需求巩检,因此需要設(shè)計(jì)新版本的 HTTP 協(xié)議。在 HTTP/1.0 協(xié)議專家組之中示启,有一位年輕人脫穎而出兢哭,顯示出了不凡的洞察力,后來他成為了 HTTP/1.1 協(xié)議專家組的負(fù)責(zé)人丑搔。這位年輕人就是 Apache HTTP 服務(wù)器的核心開發(fā)者 Roy Fielding厦瓢,他還是 Apache 軟件基金會(huì)的合作創(chuàng)始人提揍。

Roy Fielding 和他的同事們?cè)?HTTP/1.1 協(xié)議的設(shè)計(jì)工作中,對(duì)于 Web 之所以取得巨大成功煮仇,在技術(shù)架構(gòu)方面的因素做了一番深入的總結(jié)劳跃。Fielding 將這些總結(jié)納入到了一套理論框架之中,然后使用這套理論框架中的指導(dǎo)原則浙垫,來指導(dǎo) HTTP/1.1 協(xié)議的設(shè)計(jì)方向刨仑。HTTP/1.1 協(xié)議的第一個(gè)草稿是在 1996 年 1 月發(fā)布的,經(jīng)過了三年多時(shí)間的修訂夹姥,于 1999 年 6 月成為了 IETF 的正式規(guī)范(包括了 RFC 2616 以及用于對(duì)客戶端做身份認(rèn)證的 RFC 2617)杉武。HTTP/1.1 協(xié)議設(shè)計(jì)的極為成功,以至于發(fā)布之后整整 10 年時(shí)間里辙售,都沒有多少人認(rèn)為有修訂的必要轻抱。用來指導(dǎo) HTTP/1.1 協(xié)議設(shè)計(jì)的這套理論框架,最初是以備忘錄的形式在專家組成員之間交流旦部,除了 IETF/W3C 的專家圈子祈搜,并沒有在外界廣泛流傳。Fielding 在完成 HTTP/1.1 協(xié)議的設(shè)計(jì)工作之后士八,回到了加州大學(xué)歐文分校繼續(xù)攻讀自己的博士學(xué)位容燕。

第二年(2000 年)在他的博士學(xué)位論文 Architectural Styles and the Design of Network-based Software Architectures 中,F(xiàn)ielding 更為系統(tǒng)婚度、嚴(yán)謹(jǐn)?shù)仃U述了這套理論框架蘸秘,并且使用這套理論框架推導(dǎo)出了一種新的架構(gòu)風(fēng)格,并且為這種架構(gòu)風(fēng)格取了一個(gè)費(fèi)解難懂名字“REST”蝗茁,即Representational State Transfer(表現(xiàn)層狀態(tài)轉(zhuǎn)化醋虏,一般是這個(gè)翻譯,但你聽聽這是人話嗎评甜?)的縮寫.應(yīng)該是缺少了主語灰粮。全稱是 Resource Representational State Transfer:通俗來講就是:資源在網(wǎng)絡(luò)中以某種表現(xiàn)形式進(jìn)行狀態(tài)轉(zhuǎn)移。分解開來:

Resource: 資源忍坷,即數(shù)據(jù)

Representional:某種表現(xiàn)形式粘舟,比如xml,json.

State Transfer:狀態(tài)變化佩研。通過HTTP動(dòng)詞實(shí)現(xiàn)柑肴。

2.2、REST架構(gòu)的標(biāo)志

根據(jù)理查德森模型,REST架構(gòu)的成熟度有3分等級(jí)

gloryofrest.png

  • Level 0 POX(這個(gè)就不算REST了)旬薯。

    • 這類應(yīng)用只有一個(gè)URL上的上帝接口晰骑,根據(jù)交換的XML內(nèi)容操作所有的資源,往往導(dǎo)致上帝接口越來越復(fù)雜,越來越難維護(hù)硕舆。
  • Level 1 Resource秽荞。

    • 這一級(jí)別主要解決了上帝接口的問題,使得各種資源有了自己相應(yīng)URL抚官,雖然仍然是POX的交互方式扬跋,但每一個(gè)接口都更加緊湊和內(nèi)聚,相應(yīng)的容易維護(hù)起來凌节。
    • URL templating帶來的結(jié)果是服務(wù)器端和客戶端的緊耦合钦听,任何時(shí)候服務(wù)器端想改變自身的URL scheme的時(shí)候,都要break已經(jīng)存在的客戶端應(yīng)用倍奢。
    • URL tunneling帶來的問題包含URL templating,而且放棄了使用HTTP協(xié)議標(biāo)準(zhǔn)帶來的任何好處(level2中詳述)朴上。
    • 早期的rails routes就是url templating/tunneling。Rails3開始已經(jīng)更新更加靠近level 2了卒煞。
  • Level 2 Http verbs

    這一級(jí)別的使用http verbs來對(duì)各種資源進(jìn)行CRUD操作痪宰,使得應(yīng)用程序的接口更加統(tǒng)一,語義個(gè)更加明確畔裕。同時(shí)應(yīng)為遵照http協(xié)議的標(biāo)準(zhǔn)進(jìn)行交互酵镜,很多http提供的好處幾乎可以免費(fèi)的得到。此時(shí)使用多個(gè)URI的話柴钻,需要讓不同的URI代表不同的資源(注意多個(gè)URI可能指向同一個(gè)Resource,而一個(gè)URI不能指向不同Resource婉商。)渤早,同時(shí)使用多個(gè)HTTP方法操作這些資源躬络,例如使用POST/GET/PUT/DELET分別進(jìn)行CRUD操作。這時(shí)候HTTP頭和有效載荷都包含業(yè)務(wù)邏輯毫蚓,例如HTTP方法對(duì)應(yīng)CRUD操作,HTTP狀態(tài)碼對(duì)應(yīng)操作結(jié)果的狀態(tài)昔善。

    • Cache

      • 按照HTTP協(xié)議元潘,GET操作是安全的,冪等(idempotent)的君仆,任意多次對(duì)同一資源的GET操作翩概,都不會(huì)導(dǎo)致資源的狀態(tài)變化。所以GET的結(jié)果是可以安全的cache 返咱。所有http提供的cache facilities都可以被利用起來钥庇,大幅度提高了應(yīng)用程序的性能。甚至你僅僅只是在response里面加上cache directives就可以免費(fèi)獲得網(wǎng)絡(luò)上各級(jí)的緩存服務(wù)器咖摹,代理服務(wù)器评姨,以及用戶客戶端的緩存支持∮┣纾互聯(lián)網(wǎng)上幾乎所有的應(yīng)用你都可以粗略統(tǒng)計(jì)得到Get VS Non-Get的請(qǐng)求比例約為4:1吐句,如果你能為GET操作加上緩存胁后,將極大的提升你的程序性能。
    • Robust

      • 在HTTP常用的幾個(gè)動(dòng)詞里嗦枢,HRAD攀芯,GET,PUT净宵,DELETE是安全的敲才,冪等的。因?yàn)閷?duì)同一資源的任一多次請(qǐng)求择葡,永遠(yuǎn)代表同一語義紧武,所以任何時(shí)候客戶端發(fā)送出去這些動(dòng)詞的時(shí)候,如果服務(wù)器沒有響應(yīng)敏储,或者返回錯(cuò)誤代碼阻星,客戶端都可以非常安全的再執(zhí)行一次同一操作而不是擔(dān)心重復(fù)操作帶來的不同語義及最終結(jié)果。POST已添,PATCH就不是安全的妥箕,因?yàn)榭蛻舳讼蚍?wù)器端發(fā)送請(qǐng)求之后,服務(wù)器沒有響應(yīng)或者返回錯(cuò)誤代碼更舞,客戶端是不能安全的重復(fù)操作的畦幢,一定只是從新與服務(wù)器確認(rèn)現(xiàn)在的資源狀態(tài)才能決定下一步的操作。

    絕大部分的RESTful應(yīng)用就停在這里了缆蝉,當(dāng)然也滿足了大多的需求宇葱。

  • Level 3 Hypermedia controls

    • RESTful的架構(gòu)本意是“在符合架構(gòu)原理的前提下,理解和評(píng)估以網(wǎng)絡(luò)為基礎(chǔ)的應(yīng)用軟件的架構(gòu)設(shè)計(jì)刊头,得到一個(gè)功能強(qiáng)黍瞧,性能好,適宜通信的架構(gòu)”原杂。

    • 目前規(guī)模最大印颤,耦合度最低、最穩(wěn)定的穿肄、性能最好的分布式網(wǎng)絡(luò)應(yīng)用是什么年局?就是WEB本身。 規(guī)模咸产、穩(wěn)定某宪、性能都不用說,為什么耦合度低呢锐朴?想想每個(gè)人上網(wǎng)的經(jīng)歷兴喂,你幾乎不需要什么任何培訓(xùn)就可以上一個(gè)新的網(wǎng)絡(luò)購物平臺(tái)挑選商品,用信用卡付款,郵到自己家里畏鼓。把網(wǎng)站的程序想象成一個(gè)狀態(tài)機(jī),用戶在一系列的狀態(tài)轉(zhuǎn)換中完成自己的目標(biāo)壶谒,中間的每一步云矫,用用程序都告訴你當(dāng)前的狀態(tài)和可能的下一步操作,最終引導(dǎo)用戶從挑選商品到付款郵寄到家汗菜,到達(dá)狀態(tài)機(jī)的終點(diǎn)让禀。

      這種service discoverability和self-documenting就是Level 3想解決的問題。

      在這里面陨界,告訴用戶當(dāng)前的狀態(tài)以及各種下一步操作的東西巡揍,例如鏈接,按鈕等等菌瘪,就是Hypermedia Controls腮敌。Hypermedia Controls 就是這個(gè)狀態(tài)機(jī)的引擎。

      Level 3的REST架構(gòu)就是希望能夠統(tǒng)一這一類的Hypermedia Controls, 賦予他們標(biāo)準(zhǔn)的, 高度可擴(kuò)展的標(biāo)準(zhǔn)語義及表現(xiàn)形式, 使得甚至無人工干預(yù)的機(jī)器與機(jī)器間的通用交互協(xié)議邊的可能. 比如你可以告訴一個(gè)通用的購物客戶端, "給我買個(gè)最便宜的xbox", 客戶端自動(dòng)連上google進(jìn)行搜索, 自動(dòng)在前10個(gè)購物網(wǎng)站進(jìn)行搜索, 進(jìn)行價(jià)格排序, 然后自動(dòng)挑選最便宜的網(wǎng)站, 進(jìn)行一系列操作最終完成用信用卡付費(fèi), 填寫個(gè)人收件地址然后郵寄.

      這些都依賴于Hypermedia Controls帶來的這種service discoverablility和self-documenting

當(dāng)然另外一種更簡(jiǎn)便的總結(jié)式可以這樣理解:

  • REST四個(gè)基本原則:

    1. 使用HTTP動(dòng)詞:GET俏扩、 POST 糜工、PUT 、DELETE录淡;
    2. 無狀態(tài)連接捌木,服務(wù)器端不應(yīng)保存過多上下文狀態(tài),即每個(gè)請(qǐng)求都是獨(dú)立的嫉戚;
    3. 為每個(gè)資源設(shè)置URI钮莲;
    4. 通過XML JSON進(jìn)行數(shù)據(jù)傳遞;

    實(shí)現(xiàn)上述原則的架構(gòu)即可稱為RESTFul架構(gòu)彼水。

    1. 互聯(lián)網(wǎng)環(huán)境下,任何應(yīng)用的架構(gòu)和API可以被快速理解极舔;
    2. 分布式環(huán)境下凤覆,任何請(qǐng)求都可以被發(fā)送到任意服務(wù)器;
    3. 異構(gòu)環(huán)境下拆魏,任何資源的訪問和使用方式都統(tǒng)一盯桦;

RESTful簡(jiǎn)單來說就是:URL定位資源,用HTTP動(dòng)詞(GET,POST,DELETE,DETC)描述操作渤刃。

2.3拥峦、超媒體(hypermedia)

根據(jù)Roy的嚴(yán)格規(guī)定,超媒體(hypermedia)是REST的先決條件卖子,任何其他東西都不應(yīng)該自我標(biāo)榜為REST略号,這里要要先解釋一個(gè)概念:超媒體,wiki上面有這樣一個(gè)解釋:

多媒體(Multimedia),在電腦應(yīng)用系統(tǒng)中玄柠,組合兩種或兩種以上媒體的一種人機(jī)交互式資訊交流和傳播媒體突梦。使用的媒體包括文字、圖片羽利、照片宫患、聲音(包含音樂、語音旁白这弧、特殊音效)娃闲、動(dòng)畫和影片,以及程序所提供的互動(dòng)功能匾浪。

超媒體(Hypermedia)是多媒體系統(tǒng)中的一個(gè)子集皇帮,超媒體系統(tǒng)是使用超鏈接(Hyperlink)構(gòu)成的全球資訊系統(tǒng),全球資訊系統(tǒng)是互聯(lián)網(wǎng)上使用TCP/IP協(xié)議和UDP/IP協(xié)議的應(yīng)用系統(tǒng)户矢。2D的多媒體網(wǎng)頁使用HTML玲献、XML等語言編寫,3d的多媒體網(wǎng)頁使用VRML等語言編寫梯浪。目前許多多媒體作品使用光碟發(fā)行捌年,以后將更多地使用網(wǎng)絡(luò)發(fā)行。

此種關(guān)鍵的角色還是超鏈接挂洛,使用超媒體作為應(yīng)用引擎狀態(tài)礼预,意思是應(yīng)用引擎狀態(tài)變更,由客戶端訪問不同的超媒體資源驅(qū)動(dòng)虏劲。

如下示例:

GET :https://api.github.com/authorizations
{
  "author": "github",
  "video": {
    "large": "https://api.github.com/Japan/large.avi.png",
    "medium": "https://api.github.com/Japan/media.avi.png",
    "small": "https://api.github.com/Japan/small.avi.png"
  }
}

由于在響應(yīng)中包含了鏈接地址托酸,因此使用該API的客戶端就能夠自由選擇要下載怎樣的信息。這些鏈接告知了客戶端有哪些選擇柒巫,并且它們的地址在哪里励堡。

因此在這里我們無需同時(shí)返回三個(gè)不同版本小視頻,我們所做的只是告訴客戶端有三種不同清晰度可以選擇堡掏,并且告訴客戶端能夠在哪里找到這些avi应结。

這樣一來,客戶端就能夠根據(jù)不同的場(chǎng)景泉唁,做出符合自身需要的選擇鹅龄。而且,如果客戶端只需要一種高清無碼格式的亭畜,那就無需下載全部三種扮休。這樣一來可謂一箭三雕:既減少了網(wǎng)絡(luò)負(fù)載,又增進(jìn)了客戶端的靈活性拴鸵,更增進(jìn)了API的可探索性玷坠。

超媒體的核心概念就是所謂的元素蜗搔,而這些相互鏈接的資源實(shí)際上描述了一個(gè)協(xié)議,即引導(dǎo)我們達(dá)成某個(gè)目標(biāo)的一系列步驟:

例如訂購一杯咖啡所需要的點(diǎn)單侨糟、付款碍扔、取咖啡等等。這就是超媒體的本質(zhì):經(jīng)由資源之間的鏈接秕重,我們改變整個(gè)應(yīng)用的狀態(tài)不同,即超媒體轉(zhuǎn)換了,分布式應(yīng)用的狀態(tài)溶耘。需要注意的是二拐,服務(wù)器和消費(fèi)者兩者間,交換的是資源狀態(tài)的表述凳兵,而不是應(yīng)用的狀態(tài)百新,被轉(zhuǎn)移的表述中,包括了反應(yīng)庐扫,應(yīng)用狀態(tài)的鏈接饭望。

2.4、REST誤解

現(xiàn)在看來形庭,REST在2000年那個(gè)時(shí)代铅辞,確實(shí)是超前于時(shí)代的。Web開發(fā)者社區(qū)對(duì)于HTTP的設(shè)計(jì)意圖存在著大量的誤解萨醒,由此導(dǎo)致了對(duì)于HTTP的大量低效率的誤用斟珊。這個(gè)情況持續(xù)一直到2005年Web 2.0的崛起。那個(gè)時(shí)候富纸,DCOM囤踩、EJB、SOAP/WSDL這些DO風(fēng)格的架構(gòu)由于難以滿足互聯(lián)網(wǎng)環(huán)境對(duì)分布式應(yīng)用架構(gòu)設(shè)計(jì)的約束晓褪,與Web自身的架構(gòu)風(fēng)格REST相沖突堵漱,很難融入到Web之中。所謂的「Web Services」涣仿,其實(shí)除了將HTTP作為底層的傳輸協(xié)議外勤庐,跟(互聯(lián)網(wǎng)環(huán)境中的)真正的Web沒有什么關(guān)系。

而隨著Ruby on Rails這個(gè)著名的Web開發(fā)框架開始大力支持REST開發(fā)之后变过,一線的Web開發(fā)者才真正接觸到了REST。然而Rails所支持的REST開發(fā)將對(duì)資源的操作局限于CRUD(創(chuàng)建涝涤、獲取媚狰、修改、刪除)的語義(即阔拳,將對(duì)資源的CRUD操作映射到 GET/POST/PUT/DELETE四個(gè)HTTP方法)崭孤,這其實(shí)是收窄了REST的適用范圍类嗤。其他編程語言的Web開發(fā)框架(例如Java語言的 Struts、Spring MVC等等)也緊接著模仿了Rails的方式開始支持REST開發(fā)辨宠,然而這更加導(dǎo)致了一線的Web開發(fā)者誤以為:REST開發(fā)就是 通過GET/POST/PUT/DELETE四個(gè)HTTP方法對(duì)資源執(zhí)行CRUD操作遗锣。甚至還有很多僅僅使用了HTTP,而沒有使用SOAP的Web服 務(wù)API嗤形,都自稱是REST風(fēng)格(RESTful)的API精偿。

對(duì)于什么才是真正的REST風(fēng)格的誤解是如此之多,而將REST作為一個(gè)便于營(yíng)銷的 buzzword的掛羊頭賣狗肉者也是如此之多赋兵,以至于REST的創(chuàng)造者Fielding終于忍無可忍了笔咽。2008年10月Fielding寫了一篇博 客,做出了一個(gè)非常明確的斷言:REST APIs must be hypertext-driven!(REST API必須是超文本驅(qū)動(dòng)的E凇)超文本驅(qū)動(dòng)這個(gè)理念變成了一個(gè)縮寫詞HATEOAS叶组,這個(gè)縮寫詞來自于當(dāng)初Fielding博士論文中的一句話: hypermedia as the engine of application state(將超媒體作為應(yīng)用狀態(tài)的引擎)。

其實(shí)超文本驅(qū)動(dòng)(Hypertext Driven)的理念才是REST架構(gòu)風(fēng)格最核心的理念历造,也是REST風(fēng)格的架構(gòu)達(dá)到松耦合目標(biāo)的根本原因甩十。

3.REST 架構(gòu)風(fēng)格的推導(dǎo)過程

3.1 REST 所繼承的架構(gòu)風(fēng)格約束(圖 1)
restconstrain.png

在圖 1 中,每一個(gè)橢圓形里面的縮寫詞代表了一種架構(gòu)風(fēng)格吭产,而每一個(gè)箭頭邊的單詞代表了一種架構(gòu)約束侣监。

  • REST 架構(gòu)風(fēng)格最重要的架構(gòu)約束有 6 個(gè):
    • 客戶-服務(wù)器(Client-Server)

      通信只能由客戶端單方面發(fā)起,表現(xiàn)為請(qǐng)求--響應(yīng)模式垮刹。

    • 無狀態(tài)(Stateless)

      通信會(huì)話狀態(tài)(Session State)應(yīng)該全部有客戶端負(fù)責(zé)維護(hù)达吞。

    • 緩存(Cache)

      響應(yīng)內(nèi)容可以在通信連接的某處緩存,以改善網(wǎng)絡(luò)效率

    • 統(tǒng)一接口(Uniform Interface)

      通信鏈的組件之間通過統(tǒng)一的接口相互通信荒典,以提高交互的可見性酪劫。

    • 分層系統(tǒng)(Layered System)

      通過限制組件的行為(即,每個(gè)組件只能“看到”與其交互的緊鄰層)寺董,將結(jié)構(gòu)分解成若干等級(jí)覆糟。

    • 按需代碼(Code-On—Demand,可選)

      通過支持下載并執(zhí)行一些代碼(例如:Java Applet,F(xiàn)lash或者JS)遮咖,對(duì)客戶端的功能進(jìn)行擴(kuò)展滩字。

3.2. 在論文中推導(dǎo)出的 REST 架構(gòu)風(fēng)格如下圖所示:
deduce.png
3.3 .一個(gè)基于 REST 的架構(gòu)的過程視圖

而 HTTP/1.1 協(xié)議作為一種 REST 架構(gòu)風(fēng)格的架構(gòu)實(shí)例,其架構(gòu)如下圖所示:

httprestful.png

用戶代理處在三個(gè)并行交互(a麦箍、b 和 c)的中間。用戶代理的客戶端連接器緩存無法滿足請(qǐng)求陶珠,因此它根據(jù)每個(gè)資源標(biāo)識(shí)符的屬性和客戶端連接器的配置挟裂,將每個(gè)請(qǐng)求路由到資源的來源。

請(qǐng)求(a)被發(fā)送到一個(gè)本地代理揍诽,代理隨后訪問一個(gè)通過 DNS 查找發(fā)現(xiàn)的緩存網(wǎng)關(guān)诀蓉,該網(wǎng)關(guān)將這個(gè)請(qǐng)求轉(zhuǎn)發(fā)到一個(gè)能夠滿足該請(qǐng)求的來源服務(wù)器栗竖,服務(wù)器的內(nèi)部資源由一個(gè)封裝過的對(duì)象請(qǐng)求代理(object request broker)架構(gòu)來定義。

請(qǐng)求(b)直接發(fā)送到一個(gè)來源服務(wù)器渠啤,它能夠通過自己的緩存來滿足這個(gè)請(qǐng)求狐肢。

請(qǐng)求(c)被發(fā)送到一個(gè)代理,它能夠直接訪問 WAIS(一種與 Web 架構(gòu)分離的信息服務(wù))沥曹,并將 WAIS 的響應(yīng)翻譯為一種通用的連接器接口能夠識(shí)別的格式份名。每一個(gè)組件只知道與它們自己的客戶端或服務(wù)器連接器的交互;

4. 為什么要用RESTful結(jié)構(gòu)呢架专?

4.1. 從架構(gòu)風(fēng)格的抽象角度來看同窘,常見的分布式應(yīng)用架構(gòu)風(fēng)格有三種:
  • 1.分布式對(duì)象(Distributed Objects,簡(jiǎn)稱DO)

    架構(gòu)實(shí)例有 CORBA/RMI/EJB/DCOM/.NET Remoting 等等

  • 2.遠(yuǎn)程過程調(diào)用(Remote Procedure Call部脚,簡(jiǎn)稱RPC)

    架構(gòu)實(shí)例有 SOAP/XML-RPC/Hessian/Flash AMF/DWR 等等

  • 3.表現(xiàn)層狀態(tài)轉(zhuǎn)移(Representational State Transfer想邦,簡(jiǎn)稱REST)

    架構(gòu)實(shí)例有HTTP/1.1、WebDav

DO 和 RPC 這兩種架構(gòu)風(fēng)格在企業(yè)應(yīng)用中非常普遍委刘,而 REST 則是 Web 應(yīng)用的架構(gòu)風(fēng)格丧没,它們之間有非常大的差別。

4.2. REST和DO的差別在于:
  • REST支持抽象(即建模)的工具是資源锡移。DO支持抽象的工具是對(duì)象呕童。在不同的編程語言中,對(duì)象的定義有很大的差別淆珊,所以DO風(fēng)格的架構(gòu)通常都是與某種編程語言綁定的夺饲。跨語言交互即使能實(shí)現(xiàn)施符,實(shí)現(xiàn)是來也是會(huì)很復(fù)雜往声。而REST中的資源,則完全中立與開發(fā)平臺(tái)和編程語言戳吝,可以使用任何編程語言來實(shí)現(xiàn)浩销。

  • DO中沒有統(tǒng)一接口的概念。不同API听哭,接口風(fēng)格可以完全不同慢洋。DO也不支持操作語義對(duì)于中間件的可見性。

  • DO中沒有使用超文本陆盘,響應(yīng)的內(nèi)容只包含對(duì)象本身普筹。REST使用了超媒體,可以實(shí)現(xiàn)更大顆粒度的交互隘马,交互的效率比DO高太防。

  • REST支持?jǐn)?shù)據(jù)流和管道,DO不支持?jǐn)?shù)據(jù)流和管道祟霍。

  • DO風(fēng)格通常會(huì)來來客戶端和服務(wù)端的緊耦合杏头。在三種架構(gòu)風(fēng)格之中,DO風(fēng)格的耦合度是最大的沸呐,而REST的風(fēng)格耦合度是最小的醇王。REST松偶合的來源來自統(tǒng)一接口 + 超媒體驅(qū)動(dòng)。

4.3. REST與RPC的差別在于:
  • REST支持抽象的工具是資源崭添,RPC支持抽象工具是過程寓娩。REST風(fēng)格架構(gòu)建模是以名詞為核心的,RPC風(fēng)格的架構(gòu)建模是以動(dòng)詞為核心的呼渣。簡(jiǎn)單類比一下棘伴,REST是面向?qū)ο缶幊蹋琑PC則是面向過程編程屁置。

  • RPC中沒有統(tǒng)一的接口概念焊夸。不同的API,接口設(shè)計(jì)風(fēng)格可以完全不同蓝角,RPC也不支持語義對(duì)于中間件的可見性阱穗。

  • RPC沒有使用超媒體,響應(yīng)的內(nèi)容中只包含消息本身使鹅。REST使用了超媒體揪阶,可以實(shí)現(xiàn)更大顆粒度的交互效率也更高。

  • REST支持?jǐn)?shù)據(jù)流和管道患朱,RPC不支持?jǐn)?shù)據(jù)流和管道

  • 因?yàn)槭褂昧似脚_(tái)中立的消息鲁僚。RPC風(fēng)格耦合度比DO風(fēng)格小一些,但是RPC風(fēng)格也常常會(huì)帶來客戶端和服務(wù)器的緊耦合裁厅。支持統(tǒng)一接口+超媒體驅(qū)動(dòng)的風(fēng)格冰沙,可以達(dá)到最小的耦合度

4.4. REST 架構(gòu)風(fēng)格優(yōu)越之處:

比較了三種架構(gòu)風(fēng)格之間的差別之后,從面向?qū)嵱玫慕嵌葋砜唇阒保琑EST 架構(gòu)風(fēng)格可以為 Web 開發(fā)者帶來三方面的利益:

  • 簡(jiǎn)單性

采用REST架構(gòu)風(fēng)格倦淀,對(duì)于開發(fā)、測(cè)試声畏、運(yùn)維人員來說都會(huì)更簡(jiǎn)單撞叽。可以充分利用大量HTTP服務(wù)端和客戶端開發(fā)庫插龄、Web功能測(cè)試/性能測(cè)試工具愿棋、HTTP緩存、HTTP代理服務(wù)器均牢、防火墻糠雨。這些開發(fā)庫和基礎(chǔ)設(shè)施早已成為日常用品,不需要什么高科技(例如神奇昂貴的應(yīng)用服務(wù)器徘跪、中間件)就能解決大多數(shù)可伸縮性方面的問題甘邀。

  • 可伸縮性

充分利用好通訊鏈各個(gè)位置的HTTP緩存組件琅攘,可以帶來更好的伸縮性。其實(shí)很多時(shí)候松邪,在Web前端做性能優(yōu)化坞琴,產(chǎn)生的效果不亞于僅僅在服務(wù)器端做性能優(yōu)化,但是HTTP協(xié)議層面的緩存常常被一些看似很牛逼的人給忽略掉了逗抑。

  • 松耦合

統(tǒng)一接口 + 超媒體引擎驅(qū)動(dòng)剧辐,帶來了最大限度的松耦合。允許服務(wù)器和客戶端在很大范圍內(nèi)邮府,相對(duì)獨(dú)立的運(yùn)行荧关。對(duì)于設(shè)計(jì)面向企業(yè)內(nèi)網(wǎng)的API來說,松耦合并不是一個(gè)很重要的設(shè)計(jì)關(guān)注點(diǎn)褂傀。但是對(duì)于設(shè)計(jì)面向互聯(lián)網(wǎng)的API來說忍啤,松耦合成了一個(gè)必選項(xiàng),不僅僅在設(shè)計(jì)時(shí)應(yīng)該關(guān)注仙辟,而且應(yīng)該昂在最優(yōu)的位子檀轨。

下面這段話出自知乎覃超,是一個(gè)淺顯易懂的總結(jié):

大家都知道"古代"網(wǎng)頁都是前端后端融在一起的,比如之前的PHP欺嗤,JSP等参萄。在之前的桌面時(shí)代問題不大,但是近年來移動(dòng)互聯(lián)網(wǎng)的發(fā)展煎饼,各種類型的Client層出不窮讹挎,RESTful可以通過一套統(tǒng)一的接口為 Web,iOS和Android提供服務(wù)吆玖。另外對(duì)于廣大平臺(tái)來說筒溃,比如Facebook platform,微博開放平臺(tái)沾乘,微信公共平臺(tái)等怜奖,它們不需要有顯式的前端,只需要一套提供服務(wù)的接口翅阵,于是RESTful更是它們最好的選擇歪玲。在RESTful架構(gòu)下:


restful.jpg

5. RESTful如何設(shè)計(jì)

  • 1、協(xié)議

    • api與用戶的通訊協(xié)議掷匠,HTTP/HTTPS滥崩。
  • 2、域名

    • 應(yīng)盡量將API部署在專用域名之下讹语。

        https://api.example.com
      
    • 如果確定API很簡(jiǎn)單钙皮,不會(huì)有修改和進(jìn)一步的擴(kuò)展,可以考慮放在主域名下。

        https://example.com/api/...
      
  • 3短条、版本號(hào)

    • 版本號(hào)放入U(xiǎn)LR或者HTTP頭的信息中

        https://api.example.com/v1/...
      
  • 4导匣、路徑

    在RESTful的架構(gòu)中,每個(gè)網(wǎng)址代表著一種資源(resource),所以一個(gè)好的設(shè)計(jì)中茸时,網(wǎng)址中不要有動(dòng)詞逐抑,只能用名詞。其實(shí)「資源」表示一種實(shí)體屹蚊,所以應(yīng)該是名詞,動(dòng)詞應(yīng)該放在HTTP協(xié)議中进每。而與此同時(shí)URI也有可能破壞HTTP GET的安全性和幕等性汹粤,比如某個(gè)客戶端在http://example.com/updateOrder?id=1234&coffee=latte上執(zhí)行GET(而不是POST),就能創(chuàng)建一筆新的咖啡訂單(一個(gè)資源)田晚,按理來說GET請(qǐng)求不能改變服務(wù)的任何狀態(tài)嘱兼。而且所用名詞往往與數(shù)據(jù)庫中的表格對(duì)應(yīng)。一般來說贤徒,數(shù)據(jù)庫中的表都是同種記錄的集合“集合”芹壕。
    例如:API提供動(dòng)物園(zoo)的信息,可以這樣設(shè)計(jì)接奈;

      https://api.example.com/v1/zoos
      https://api.example.com/v1/animals
      https://api.example.com/v1/dogs
    
  • 5踢涌、HTTP動(dòng)詞

    • GET :用來獲取資源,
    • POST :用來新建資源(也可以用于更新資源)序宦,
    • PUT :用來更新資源睁壁,
    • DELETE :用來刪除資源。
    • PATCH(UPDATE):在服務(wù)器更新資源(客戶端提供改變的屬性)互捌。
    • HEAD:獲取資源的元數(shù)據(jù)潘明。
    • PTIONS:獲取信息,關(guān)于資源的哪些屬性是客戶端可以改變的秕噪。
  • 6钳降、過濾信息

    如果記錄數(shù)量很多,服務(wù)器不可能都將他們返回給用戶腌巾。API提供參數(shù)返回過濾后的數(shù)據(jù):

      * ?limit=10:指定返回記錄的數(shù)量
      * ?offset=10:指定返回記錄開始的位置
      * ?page-2&per_page=100:指定第幾頁以及每頁的返回?cái)?shù)量
      * ?sortby=name&order=asc:指定返回結(jié)果按照哪個(gè)屬性排序遂填,以及排序順序
      * ?animal_type_id=1:指定篩選條件
    

    參數(shù)的設(shè)計(jì)允許存在冗余,即允許API路徑和URL參數(shù)偶爾有重復(fù)澈蝙。比如城菊,GET /zoo/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的。

  • 7碉克、狀態(tài)碼

服務(wù)器向用戶返回的狀態(tài)碼和提示信息凌唬,常見的有以下一些(方括號(hào)中是該狀態(tài)碼對(duì)應(yīng)的HTTP動(dòng)詞),查看全部狀態(tài)碼定義點(diǎn)擊這里

* 200 OK-[GET]:服務(wù)器成功返回請(qǐng)求數(shù)據(jù),該操作是冪等的客税。
* 201 create -[POST/PUT/PATCH]:用戶新建或者修改數(shù)據(jù)
* 202 Accept - [*]標(biāo)識(shí)一個(gè)請(qǐng)求進(jìn)入后臺(tái)排隊(duì)(異步任務(wù))
* 204 no content - [DELETE]:用戶刪除數(shù)據(jù)成功
* 400 invalid requests- [POST/PUT/PATCH]:用戶發(fā)出的請(qǐng)求錯(cuò)誤况褪,服務(wù)器沒有進(jìn)行新建或者修改的操作,該操作是冪等的更耻。
* 401 Unauthorized- [*]:標(biāo)識(shí)沒有權(quán)限(令牌测垛,用戶名,密碼錯(cuò)誤)秧均。
* 403 Forbidden - [*]: 標(biāo)識(shí)用戶得到授權(quán)(與401錯(cuò)誤相對(duì))食侮,但是訪問是被禁止的。
* 404 not found - [*]: y用戶發(fā)出的請(qǐng)求針對(duì)的是不是存在的記錄目胡,服務(wù)器沒進(jìn)行操作锯七,這個(gè)操作是冪等的。
* 406 Not Acceptable - [GET]:用戶請(qǐng)求格式不可得:(比如用戶請(qǐng)求的是json格式誉己,但是只要xml格式)
* 410 Gone - [GET]:用戶請(qǐng)求資源被永久刪除眉尸,且不會(huì)再得到。
* 422 Unprocesable entity - [POST/PUT/PATCH]當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)候巨双,發(fā)生一個(gè)驗(yàn)證錯(cuò)誤噪猾。
* 500 internal server error - [*] :服務(wù)器發(fā)生錯(cuò)誤,用戶將無法判斷發(fā)出的請(qǐng)求是否成功筑累。

另外附上GitHub的API設(shè)計(jì),更具參考價(jià)值袱蜡。

6. 各端的具體實(shí)現(xiàn)

如上圖說是,service統(tǒng)一提供了一套R(shí)ESTful API, web+android+ios作為同級(jí)調(diào)用API慢宗,現(xiàn)在都有一些比較成熟的框架來幫助開發(fā)者戒劫。

1. Server

2. Android

3. iOS

4. Web

  • 可以用重量級(jí)的AngularJS,也可以用輕量級(jí) Backbone + jQuery 等婆廊。

7. Django REST Framework使用

Django REST Framework應(yīng)用會(huì)在下一遍文章中做詳細(xì)分析迅细。

參考資料鏈接:

REST APIs must be hypertext-driven

REST 架構(gòu)該怎么生動(dòng)地理解?

理解RESTful架構(gòu)

RESTful API 設(shè)計(jì)指南

Richardson Maturity Model

Status Code Definitions

理解本真的 REST 架構(gòu)風(fēng)格

架構(gòu)風(fēng)格與基于網(wǎng)絡(luò)的軟件架構(gòu)設(shè)計(jì)(Roy Fielding 博士論文中文版)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淘邻,一起剝皮案震驚了整個(gè)濱河市茵典,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宾舅,老刑警劉巖统阿,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異筹我,居然都是意外死亡扶平,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門蔬蕊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來结澄,“玉大人,你說我怎么就攤上這事÷橄祝” “怎么了们妥?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)勉吻。 經(jīng)常有香客問我监婶,道長(zhǎng),這世上最難降的妖魔是什么齿桃? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任惑惶,我火速辦了婚禮,結(jié)果婚禮上短纵,老公的妹妹穿的比我還像新娘带污。我一直安慰自己,他們只是感情好踩娘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著喉祭,像睡著了一般养渴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泛烙,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天理卑,我揣著相機(jī)與錄音,去河邊找鬼蔽氨。 笑死藐唠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鹉究。 我是一名探鬼主播宇立,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼自赔!你這毒婦竟也來了妈嘹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤绍妨,失蹤者是張志新(化名)和其女友劉穎润脸,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體他去,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毙驯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了灾测。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆价。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出允坚,到底是詐尸還是另有隱情魂那,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布稠项,位于F島的核電站涯雅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏展运。R本人自食惡果不足惜活逆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拗胜。 院中可真熱鬧蔗候,春花似錦、人聲如沸埂软。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勘畔。三九已至所灸,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炫七,已是汗流浹背爬立。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留万哪,地道東北人侠驯。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像奕巍,于是被迫代替她去往敵國和親吟策。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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