一套設(shè)計(jì)良好的RESTful API如何成為前后端的橋梁?

移動(dòng)互聯(lián)網(wǎng)時(shí)代,RESTful API成為越來越重要的移動(dòng)端和服務(wù)器端交互的形式。尤其是在很多互聯(lián)網(wǎng)公司或者傳統(tǒng)行業(yè)擁抱移動(dòng)互聯(lián)網(wǎng)的時(shí)候,一套設(shè)計(jì)良好的Restful API能夠幫助互聯(lián)網(wǎng)產(chǎn)品支持單服務(wù)端+多客戶端的場景。RESTful架構(gòu)本身是一個(gè)風(fēng)格而不是一個(gè)標(biāo)準(zhǔn),這也就意味著在具體設(shè)計(jì)時(shí)會(huì)有不同的實(shí)現(xiàn)。那么什么是好的RESTful API呢?筆者認(rèn)為適合的是最好的,能夠根據(jù)本身產(chǎn)品的業(yè)務(wù)場景和階段設(shè)計(jì)出結(jié)構(gòu)清晰,易于理解,擴(kuò)展方便的Restful API 就是最好的。本文將圍繞筆者對Restful架構(gòu)的理解展開討論,歡迎大家拍磚。

1、什么是RESTful API

表征性狀態(tài)傳輸(Representational State Transfer,簡稱REST )是Roy Fielding博士于2000年在他的博士論文中提出來的一種軟件架構(gòu)風(fēng)格。如果一個(gè)架構(gòu)符合REST原則,就稱它為RESTful架構(gòu)。說到Roy Fielding幾乎可以稱之為HTTP協(xié)議之父,他是HTTP1.0和1.1的主要設(shè)計(jì)者,這篇基于HTTP協(xié)議的軟件架構(gòu)風(fēng)格一出世就引起了關(guān)注并對互聯(lián)網(wǎng)開發(fā)產(chǎn)生了深遠(yuǎn)的影響。發(fā)展到今日主流開源框架都提供了對REST的支持,大多數(shù)互聯(lián)網(wǎng)公司都采用了RESTful架構(gòu)。

2、資源(Resources)是REST的核心

REST開發(fā)又被稱作“面向資源的開發(fā)”,這說明對于資源的抽象是設(shè)計(jì)RESTful API的核心內(nèi)容。RESTful API建模的過程與面向?qū)ο蠼n愃?,是以名詞為核心的。這些名詞就是資源,任何可命名的抽象概念都可以定義為一個(gè)資源。對于業(yè)務(wù)的抽象是設(shè)計(jì)一套好的RESTful API的基礎(chǔ),這就好比建房子打地基,如果地基沒有打好,后面建的樓就很容易歪掉,其美觀度,可維護(hù)性,可擴(kuò)展性就會(huì)大大折扣。筆者會(huì)建議在設(shè)計(jì)初期一定要在資源的定義上多花功夫,抽象出適合業(yè)務(wù)發(fā)展的資源。也就是說一開始要把產(chǎn)品的RESTful風(fēng)格定義下來,后面的擴(kuò)展都可以基于這樣的風(fēng)格延續(xù)下去。

下面是幾條小的建議:

-理清資源的層次結(jié)構(gòu),比如業(yè)務(wù)針對的范圍是學(xué)校,那么學(xué)校會(huì)是一級資源(/school),老師(/school/teachers),學(xué)生(school/students)就是二級資源。

-資源盡量用準(zhǔn)確的英文名詞去表達(dá),資源組都用復(fù)數(shù)來表達(dá)。一個(gè)好的資源定義一定是自解釋的,也就是說你只需要很少的先驗(yàn)信息就能理解這個(gè)resource資源代表什么意思。

3、資源的狀態(tài)轉(zhuǎn)化(State Transfer)

訪問一個(gè)網(wǎng)站,代表的就是客戶端和服務(wù)器的一個(gè)互動(dòng)過程,這個(gè)過程中勢必就涉及到數(shù)據(jù)和狀態(tài)的變化。而廣為使用的HTTP協(xié)議又恰恰是無狀態(tài)的協(xié)議,這就意味這所有的狀態(tài)都保存在服務(wù)器端。如果某個(gè)客戶端想要操作服務(wù)器端必須通過某種手段讓服務(wù)器發(fā)生狀態(tài)轉(zhuǎn)換。那么客戶端可以操作的就是上文所定義的資源,而資源的狀態(tài)轉(zhuǎn)化就轉(zhuǎn)化為對資源的各種操作。這些操作是通過HTTP協(xié)議的四種常用的方法來實(shí)現(xiàn):GET,POST,PUT,DELETE。他們分別對應(yīng)四種基本操作:GET-獲取資源,POST-新建或者更新資源,PUT-更新資源,DELETE-刪除資源。還有其它不常用的HTTP方法:PATCH/HEAD/OPTIONS方法。

對于HTTP方法的應(yīng)用業(yè)界一直有兩種聲音:

-一種是盡量使用所有的HTTP方法去操作資源,請求里面只能帶資源不能出現(xiàn)任何動(dòng)詞,如果發(fā)現(xiàn)資源上的操作過多以至于HTTP的方法不夠用,應(yīng)該考慮設(shè)計(jì)出更多的資源。這種方式適用于新產(chǎn)品的開發(fā),產(chǎn)品是從建模開始的,可以充分的考慮各種業(yè)務(wù)場景定義出相應(yīng)的資源。

-另一種是就是靈活適用,用GET去獲取資源,其它涉及更改的操作都用POST,并當(dāng)POST不能表達(dá)相應(yīng)的動(dòng)作時(shí)在URL中添加動(dòng)詞。比如在二手商品市場我發(fā)布了一個(gè)售賣手機(jī)的資源。那么對于這個(gè)資源,賣家本人可以對這個(gè)商品有取消的操作:POST /resources/123/cancel;買家可以對這個(gè)商品有購買的操作:POST /resources/123/buy。這種方式適用于對現(xiàn)有非RESTful架構(gòu)進(jìn)行升級改造而修改模型影響更大的業(yè)務(wù)產(chǎn)品。當(dāng)然這種選擇也有可能是前后端程序猿們協(xié)商的結(jié)果,畢竟用一種最自然的溝通方式去架起前后端的橋梁才是目的所在。

4、合理使用URL路徑參數(shù)和請求

在URL路徑里的參數(shù)一定是代表某個(gè)資源的ID,路徑參數(shù)也可以是多個(gè)代表幾級資源的IDs,例如獲取一個(gè)老師所帶班級的詳情/teachers/#teacher_id/classes/#class_id。

對于HTTP GET,請求參數(shù)一般是作為可選參數(shù)獲取某個(gè)資源列表的子集,例如獲取年青老師的列表/teachers?group=young。

對于HTTP POST,請求參數(shù)是在消息體里,代表需要新建或者更新的資源。

5、合理使用HTTP響應(yīng)代碼

HTTP響應(yīng)狀態(tài)代碼,是HTTP協(xié)議這個(gè)統(tǒng)一接口中用來表達(dá)出錯(cuò)情況的標(biāo)準(zhǔn)機(jī)制。響應(yīng)狀態(tài)代碼分成兩部分:狀態(tài)碼和原因。兩部分都是可定制的,也可以使用標(biāo)準(zhǔn)的狀態(tài)碼,只定制出錯(cuò)原因。在實(shí)際應(yīng)用中也是兩種選擇:

?一種是對于應(yīng)用出錯(cuò)的情況擴(kuò)展?fàn)顟B(tài)碼,定制出錯(cuò)原因。

?一種是對于容器處理的出錯(cuò)情況默認(rèn)使用容器返回的錯(cuò)誤碼,例如tomcat容器返回的503,404;而對于應(yīng)用本身返回的狀態(tài)碼一律返回200,對于應(yīng)用出錯(cuò)碼和原因都反應(yīng)在返回消息體中。

6、定義一套標(biāo)準(zhǔn)的返回體數(shù)據(jù)結(jié)構(gòu)

對于所有的RESTful HTTP請求定義一套標(biāo)準(zhǔn)的返回結(jié)構(gòu)體,前端可以根據(jù)這樣的固定格式做標(biāo)準(zhǔn)化的解析,對于系統(tǒng)的可維護(hù)性起到很大的幫助。這個(gè)結(jié)構(gòu)體里應(yīng)該包含返回的具體資源,結(jié)果狀態(tài)碼和錯(cuò)誤原因(如果有的話)。對于返回的資源,數(shù)據(jù)類型也盡量做到統(tǒng)一,比如日期,枚舉類型都返回統(tǒng)一的數(shù)據(jù)類型避免不同的API對同一種數(shù)據(jù)有不同的處理方式。資源屬性盡量做到可讀也能大大減少前后端的溝通成本。

7、RESTful API的版本控制

一個(gè)簡單的做法是直接在URL中插入版本號(hào),這樣可以允許多個(gè)版本的API同時(shí)運(yùn)行。在已經(jīng)發(fā)布的版本中盡量做到向后兼容,包括URL和參數(shù),對于返回值也是盡量增加新的冗余參數(shù)以兼容不同客戶端不同的升級頻率。等到所有的客戶端升級以后再去除冗余的過程。

8、RESTful API的安全性

安全性也是一個(gè)很大的話題,如果展開來講又將是另外一篇文章。簡單來講主要是要考慮下面幾個(gè)方面:

-對客戶端做身份認(rèn)證

-保證每個(gè)用戶只能操作自己的資源,而不會(huì)CRUD屬于別人的資源

-對于敏感數(shù)據(jù)做加密防止串改

-對于POST請求添加冪等機(jī)制以保證對資源的增加或者修改是安全的。

結(jié)語

最后作為結(jié)束語,想說明的是一套設(shè)計(jì)良好的RESTful一定是前后端反復(fù)溝通協(xié)商并不斷迭代的過程。因?yàn)镽ESTful API作為前后端的橋梁我們需要同時(shí)考慮前后端的需求并達(dá)成一致的一個(gè)結(jié)果,橋梁之所以成為橋梁一定是雙方都認(rèn)可的溝通方式。架構(gòu)是一門科學(xué),也是一種藝術(shù)。

本文作者:陳琨(點(diǎn)融黑幫),現(xiàn)任點(diǎn)融網(wǎng)資深軟件開發(fā)工程師。曾就職于愛立信、華為、關(guān)注與高并發(fā)高可用的互聯(lián)網(wǎng)軟件系統(tǒng)設(shè)計(jì)和開發(fā)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容