前端學(xué)習(xí)【RESTful架構(gòu)篇】

前記:一開始原本是想用自己的語言寫一篇關(guān)于RESTful架構(gòu)的文章祠饺,然而無奈于自己也是剛剛接觸哩牍,怕理解不到位有誤導(dǎo)讀者之嫌玲昧,故重新將這篇文章定位為了本人的RESRful學(xué)習(xí)路徑疗垛。若有錯誤罢洲,還請大家指正乱灵。

什么是RESTful架構(gòu)塑崖?


參考文獻(xiàn):理解 RESTful 架構(gòu) - 阮一峰

注:以下內(nèi)容都引用自該文獻(xiàn)

REST這個詞,是Roy Thomas Fielding在他2000年的博士論文中提出的痛倚。Fielding是一個非常重要的人规婆,他是HTTP協(xié)議(1.0版和1.1版)的主要設(shè)計(jì)者、Apache服務(wù)器軟件的作者之一蝉稳、Apache基金會的第一任主席抒蚜。所以,他的這篇論文一經(jīng)發(fā)表耘戚,就引起了關(guān)注嗡髓,并且立即對互聯(lián)網(wǎng)開發(fā)產(chǎn)生了深遠(yuǎn)的影響。

Fielding將他對互聯(lián)網(wǎng)軟件的架構(gòu)原則收津,定名為REST饿这,即Representational State Transfer的縮寫浊伙。我對這個詞組的翻譯是"表現(xiàn)層狀態(tài)轉(zhuǎn)化"

如果一個架構(gòu)符合REST原則长捧,就稱它為RESTful架構(gòu)嚣鄙。

要理解RESTful架構(gòu),最好的方法就是去理解Representational State Transfer這個詞組到底是什么意思串结,它的每一個詞代表了什么涵義哑子。如果你把這個名稱搞懂了,也就不難體會REST是一種什么樣的設(shè)計(jì)奉芦。

REST的名稱"表現(xiàn)層狀態(tài)轉(zhuǎn)化"中赵抢,省略了主語。"表現(xiàn)層"其實(shí)指的是"資源"(Resources)的"表現(xiàn)層"声功。

所謂"資源"烦却,就是網(wǎng)絡(luò)上的一個實(shí)體,或者說是網(wǎng)絡(luò)上的一個具體信息先巴。它可以是一段文本其爵、一張圖片、一首歌曲伸蚯、一種服務(wù)摩渺,總之就是一個具體的實(shí)在。你可以用一個URI(統(tǒng)一資源定位符)指向它剂邮,每種資源對應(yīng)一個特定的URI摇幻。要獲取這個資源,訪問它的URI就可以挥萌,因此URI就成了每一個資源的地址或獨(dú)一無二的識別符绰姻。

"資源"是一種信息實(shí)體,它可以有多種外在表現(xiàn)形式引瀑。我們把"資源"具體呈現(xiàn)出來的形式狂芋,叫做它的"表現(xiàn)層"(Representation)

比如憨栽,文本可以用txt格式表現(xiàn)帜矾,也可以用HTML格式、XML格式屑柔、JSON格式表現(xiàn)屡萤,甚至可以采用二進(jìn)制格式;圖片可以用JPG格式表現(xiàn)锯蛀,也可以用PNG格式表現(xiàn)灭衷。

訪問一個網(wǎng)站,就代表了客戶端和服務(wù)器的一個互動過程旁涤。在這個過程中翔曲,勢必涉及到數(shù)據(jù)和狀態(tài)的變化迫像。

互聯(lián)網(wǎng)通信協(xié)議HTTP協(xié)議,是一個無狀態(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協(xié)議舔箭。具體來說,就是HTTP協(xié)議里面蚊逢,四個表示操作方式的動詞:GET层扶、POST、PUT烙荷、DELETE镜会。它們分別對應(yīng)四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源)终抽,PUT用來更新資源戳表,DELETE用來刪除資源。

優(yōu)秀的RESTful架構(gòu)需要具備哪些特質(zhì)昼伴?


參考文獻(xiàn):Principles of good RESTful API Design - (譯:好 RESTful API 的設(shè)計(jì)原則 - moonz-wu)

注:以下內(nèi)容都引用自該文獻(xiàn)

這里有一些非常重要的術(shù)語扒袖,我將在本文里面一直用到它們:

資源:一個對象的單獨(dú)實(shí)例,如一只動物
集合:一群同種對象亩码,如動物
HTTP:跨網(wǎng)絡(luò)的通信協(xié)議
客戶端:可以創(chuàng)建HTTP請求的客戶端應(yīng)用程序
第三方開發(fā)者:這個開發(fā)者不屬于你的項(xiàng)目但是有想使用你的數(shù)據(jù)
服務(wù)器:一個HTTP服務(wù)器或者應(yīng)用程序,客戶端可以跨網(wǎng)絡(luò)訪問它
端點(diǎn):這個API在服務(wù)器上的URL用于表達(dá)一個資源或者一個集合
冪等:無邊際效應(yīng)野瘦,多次操作得到相同的結(jié)果
URL段:在URL里面已斜杠分隔的內(nèi)容

一描沟、四個半非常重要的HTTP動詞

這里至少有四個半非常重要的HTTP動詞需要你知道。我之所以說“半個”的意思是PATCH這個動詞非常類似于PUT鞭光,并且它們倆也常常被開發(fā)者綁定到同一個API上吏廉。

GET (選擇):從服務(wù)器上獲取一個具體的資源或者一個資源列表。
POST (創(chuàng)建): 在服務(wù)器上創(chuàng)建一個新的資源惰许。
PUT (更新):以整體的方式更新服務(wù)器上的一個資源席覆。
PATCH (更新):只更新服務(wù)器上一個資源的一個屬性。
DELETE (刪除):刪除服務(wù)器上的一個資源汹买。
還有兩個不常用的HTTP動詞:

HEAD : 獲取一個資源的元數(shù)據(jù)佩伤,如數(shù)據(jù)的哈希值或最后的更新時間聊倔。
OPTIONS:獲取客戶端能對資源做什么操作的信息。

一個好的RESTful API只允許第三方調(diào)用者使用這四個半HTTP動詞進(jìn)行數(shù)據(jù)交互生巡,并且在URL段里面不出現(xiàn)任何其他的動詞耙蔑。

二、版本信息

無論你正在構(gòu)建什么孤荣,無論你在入手前做了多少計(jì)劃甸陌,你核心的應(yīng)用總會發(fā)生變化,數(shù)據(jù)關(guān)系也會變化盐股,資源上的屬性也會被增加或刪除钱豁。只要你的項(xiàng)目還活著,并且有大量的用戶在用疯汁,這種情況總是會發(fā)生牲尺。

請謹(jǐn)記一點(diǎn),API是服務(wù)器與客戶端之間的一個公共契約涛目。如果你對服務(wù)器上的API做了一個更改秸谢,并且這些更改無法向后兼容,那么你就打破了這個契約霹肝,客戶端又會要求你重新支持它估蹄。為了避免這樣的事情,你既要確保應(yīng)用程序逐步的演變沫换,又要讓客戶端滿意臭蚁。那么你必須在引入新版本API的同時保持舊版本API仍然可用。

注:如果你只是簡單的增加一個新的特性到API上讯赏,如資源上的一個新屬性或者增加一個新的端點(diǎn)垮兑,你不需要增加API的版本。因?yàn)檫@些并不會造成向后兼容性的問題漱挎,你只需要修改文檔即可系枪。

隨著時間的推移,你可能聲明不再支持某些舊版本的API磕谅。申明不支持一個特性并不意味著關(guān)閉或者破壞它私爷。而是告訴客戶端舊版本的API將在某個特定的時間被刪除,并且建議他們使用新版本的API膊夹。

一個好的RESTful API會在URL中包含版本信息衬浑。另一種比較常見的方案是在請求頭里面保持版本信息。但是跟很多不同的第三方開發(fā)者一起工作后放刨,我可以很明確的告訴你工秩,在請求頭里面包含版本信息遠(yuǎn)沒有放在URL里面來的容易。

三、簡潔的API根入口點(diǎn)

無論你信不信助币,API的根地址很重要浪听。當(dāng)一個開發(fā)者接手了一個舊項(xiàng)目(如進(jìn)行代碼考古時)。而這個項(xiàng)目正在使用你的API奠支,同時開發(fā)者還想構(gòu)建一個新的特性馋辈,但他們完全不知道你的服務(wù)。幸運(yùn)的是他們知道客戶端對外調(diào)用的那些URL列表倍谜。讓你的API根入口點(diǎn)保持盡可能的簡單是很重要的迈螟,因?yàn)殚_發(fā)者很可能一看到那些冗長而又復(fù)雜的URL就轉(zhuǎn)身而走。

這里有兩個常見的URL根例子:

https://example.org/api/v1/*
https://api.example.com/v1/*
如果你的應(yīng)用很龐大或者你預(yù)期它將會變的很龐大尔崔,那么將API放到子域下通常是一個好選擇答毫。這種做法可以保持某些規(guī)模化上的靈活性季春。

但如果你覺得你的API不會變的很龐大洗搂,或是你只是想讓應(yīng)用安裝更簡單些(如你想用相同的框架來支持站點(diǎn)和API),將你的API放到根域名下也是可以的载弄。

讓API根擁有一些內(nèi)容通常也是個好主意耘拇。Github的API根就是一個典型的例子。從個人角度來說我是一個通過根URL發(fā)布信息的粉絲宇攻,這對很多人來說是有用的惫叛,例如如何獲取API相關(guān)的開發(fā)文檔。

同樣也請注意HTTPS前綴逞刷,一個好的RESTful API總是基于HTTPS來發(fā)布的嘉涌。

四、減少無謂的限制

當(dāng)客戶端創(chuàng)建了一個請求來獲取一個對象列表時夸浅,很重要一點(diǎn)就是你要返回給他們一個符合查詢條件的所有對象的列表仑最。這個列表可能會很大。但你不能隨意給返回?cái)?shù)據(jù)的數(shù)量做限制帆喇。因?yàn)檫@些無謂的限制會導(dǎo)致第三方開發(fā)者不知道發(fā)生了什么警医。如果他們請求一個確切的集合并且要遍歷結(jié)果,然而他們發(fā)現(xiàn)只拿到了100條數(shù)據(jù)坯钦。接下來他們就不得不去查找這個限制條件的出處法严。到底是ORM的bug導(dǎo)致的,還是因?yàn)榫W(wǎng)絡(luò)截?cái)嗔舜髷?shù)據(jù)包葫笼?

盡可能減少那些會影響到第三方開發(fā)者的無謂限制

這點(diǎn)很重要,但你可以讓客戶端自己對結(jié)果做一些具體的過濾或限制拗馒。這么做最重要的一個原因是可以最小化網(wǎng)絡(luò)傳輸路星,并讓客戶端盡可能快的得到查詢結(jié)果。其次是客戶端可能比較懶,如果這時服務(wù)器能對結(jié)果做一些過濾或分頁洋丐,對大家都是好事呈昔。另外一個不那么重要的原因是(從客戶端角度來說),對服務(wù)器來說響應(yīng)請求的負(fù)載越少越好友绝。

四堤尾、符合標(biāo)準(zhǔn)的狀態(tài)碼

對于一個RESTful API來說很重要的一點(diǎn)就是要使用HTTP的狀態(tài)碼,因?yàn)樗鼈兪荋TTP的標(biāo)準(zhǔn)迁客。很多的網(wǎng)絡(luò)設(shè)備都可以識別這些狀態(tài)碼郭宝,例如負(fù)載均衡器可能會通過配置來避免發(fā)送請求到一臺web服務(wù)器,如果這臺服務(wù)器已經(jīng)發(fā)送了很多的50x錯誤回來掷漱。

1xx范圍的狀態(tài)碼是保留給底層HTTP功能使用的粘室,并且估計(jì)在你的職業(yè)生涯里面也用不著手動發(fā)送這樣一個狀態(tài)碼出來。

2xx范圍的狀態(tài)碼是保留給成功消息使用的卜范,你盡可能的確保服務(wù)器總發(fā)送這些狀態(tài)碼給用戶衔统。

3xx范圍的狀態(tài)碼是保留給重定向用的。大多數(shù)的API不會太常使用這類狀態(tài)碼海雪,但是在新的超媒體樣式的API中會使用更多一些锦爵。

4xx范圍的狀態(tài)碼是保留給客戶端錯誤用的。例如奥裸,客戶端提供了一些錯誤的數(shù)據(jù)或請求了不存在的內(nèi)容险掀。這些請求應(yīng)該是冪等的,不會改變?nèi)魏畏?wù)器的狀態(tài)刺彩。

5xx范圍的狀態(tài)碼是保留給服務(wù)器端錯誤用的迷郑。這些錯誤常常是從底層的函數(shù)拋出來的,并且開發(fā)人員也通常沒法處理创倔。發(fā)送這類狀態(tài)碼的目的是確蔽撕Γ客戶端能得到一些響應(yīng)。收到5xx響應(yīng)后畦攘,客戶端沒辦法知道服務(wù)器端的狀態(tài)霸妹,所以這類狀態(tài)碼是要盡可能的避免。

五知押、完善的API文檔

老實(shí)說叹螟,即使你不能百分之百的遵循指南中的條款,你的API也不是那么糟糕台盯。但是罢绽,如果你不為API準(zhǔn)備文檔的話,沒有人會知道怎么使用它静盅,那它真的會成為一個糟糕的API良价。

讓你的文檔對那些未經(jīng)認(rèn)證的開發(fā)者也可用

不要使用文檔自動化生成器,即便你用了,你也要保證自己審閱過并讓它具有更好的版式明垢。
不要截?cái)嗍纠姓埱笈c響應(yīng)的內(nèi)容蚣常,要展示完整的東西。并在文檔中使用高亮語法痊银。

文檔化每一個端點(diǎn)所預(yù)期的響應(yīng)代碼和可能的錯誤消息抵蚊,和在什么情況下會產(chǎn)生這些的錯誤消息

如果你有富余的時間,那就創(chuàng)建一個控制臺來讓開發(fā)者可以立即體驗(yàn)一下API的功能溯革。創(chuàng)建一個控制臺并沒有想象中那么難贞绳,并且開發(fā)者們(內(nèi)部或者第三方)也會因此而擁戴你。

另外確保你的文檔能夠被打印鬓照。CSS是個強(qiáng)大的工具可以幫助到你熔酷。而且在打印的時候也不用太擔(dān)心邊側(cè)欄的問題。即便沒有人會打印到紙上豺裆,你也會驚奇的發(fā)現(xiàn)很多開發(fā)者愿意轉(zhuǎn)化成PDF格式進(jìn)行離線閱讀拒秘。

六、提供主流數(shù)據(jù)格式

目前臭猜,大多數(shù)“精彩”的API都為RESTful接口提供JSON數(shù)據(jù)躺酒。諸如Facebook,Twitter蔑歌,Github等等你所知的羹应。XML曾經(jīng)也火過一把(通常在一個大企業(yè)級環(huán)境下)。這要感謝SOAP次屠,不過它已經(jīng)掛了园匹,并且我們也沒看到太多的API把HTML作為結(jié)果返回給客戶端(除非你在構(gòu)建一個爬蟲程序)。

只要你返回給他們有效的數(shù)據(jù)格式劫灶,開發(fā)者就可以使用流行的語言和框架進(jìn)行解析裸违。如果你正在構(gòu)建一個通用的響應(yīng)對象,通過使用一個不同的序列化器本昏,你也可以很容易的提供之前所提到的那些數(shù)據(jù)格式(不包括SOAP)供汛。而你所要做的就是把使用方式放在響應(yīng)數(shù)據(jù)的接收頭里面。

有些API的創(chuàng)建者會推薦把.json, .xml, .html等文件的擴(kuò)展名放在URL里面來指示返回內(nèi)容類型涌穆,但我個人并不習(xí)慣這么做怔昨。我依然喜歡通過接收頭來指示返回內(nèi)容類型(這也是HTTP標(biāo)準(zhǔn)的一部分),并且我覺得這么做也比較適當(dāng)一些宿稀。

最后編輯于
?著作權(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)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理壶运,服務(wù)發(fā)現(xiàn),斷路器浪秘,智...
    卡卡羅2017閱讀 134,696評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,280評論 25 707
  • 一說到REST蒋情,我想大家的第一反應(yīng)就是“啊埠况,就是那種前后臺通信方式】醚ⅲ”但是在要求詳細(xì)講述它所提出的各個約束辕翰,以及如...
    時待吾閱讀 3,433評論 0 19
  • 譯者:知秋(極樂科技專欄作者)來源:https://zhuanlan.zhihu.com/p/24592119 當(dāng)...
    極樂君閱讀 1,203評論 0 14
  • 安婧_52d6閱讀 134評論 0 0