看了兩天 RESTful 總結的筆記,第一次在掘金髮文章,如有謬誤還請大佬們海涵。html
REST(Representational State Transfer)是種互聯網軟件架構模式,由 Roy Fielding 在他 2000 年的博士論文《架構風格與基於網絡的軟件架構設計》(譯)中提出,REST 一經提出就流行起來, 迅速取代了複雜笨重的 SOAP。前端
要理解 REST,最好是認真理解 Representational State Transfer 是什麼,它的直譯是「表現層狀態轉化」,其中省略了主語,完整的意思應該是「資源的表現層狀態轉化」,關鍵詞是「資源」、「表現層」、「狀態轉化」。git
「資源」就是網絡上的一個信息實體,REST 規定用一個 URI(統一資源定位符)來惟一標識一個資源,經過 URI 能夠獲取到任意資源。github
「資源」只是信息,它能夠有多種存在方式(好比一段單純的文本能夠被表示爲 txt、HTML、XML、JSON,甚至二進制等多種格式),咱們把資源所處的存在方式稱爲它的「表現層」, 能夠把「表現層」理解爲資源的「視圖」,在 REST 裏,URI 只用來標識資源,並不標識它處於哪一個表現層,它的表現層是在 HTTP header 中由 Accept、Content-Type 指定的,這兩個字段用於標識資源當前所處 的「表現層」。web
「狀態」包括資源自己信息和它所處的表現層兩個方面(這個概念多是我造的,我查的資料裏並無把「狀態」做爲一個單獨的概念過,但我以爲應該加這麼個概念,否則邏輯上有些不通), 「狀態轉化」是指資源從一種「狀態」改變到另外一種「狀態」,這個「改變」多是表現層的改變,也多是資源自己信息的改變,訪問接口,就是通知服務端進行「狀態轉化」, 好比 CURD:sql
操做 | 影響 |
---|---|
增 | 信息改變,多了一些信息。 |
刪 | 信息改變,少了一些信息。 |
改 | 信息改變,變了一些信息。 |
查 | 表現層改變,數據被從數據庫中取出轉爲 html、json 等。 |
REST 規定用 HTTP method 來做爲告知服務端進行「狀態轉化」的手段,具體的說就是用 HTTP 的不一樣請求方法來指定不一樣的操做,好比常見的 GET、POST、PUT、DELETE 分別對應 CURD, 告知服務端進行增刪改查四種狀態轉化。數據庫
以上是 REST 的核心概念,嚴格來講它有如下幾條約束:json
若是一個架構符合 REST 的規範,就稱它爲 RESTful 架構,採用 RESTful 架構的 web 服務也被稱爲 Restful web service。後端
在 Restful web service 中,每一個 url 表明一種資源(resource),因此 url 中不能有動詞,只能有名詞,甚至所用的名詞每每與數據表名相對應,而數據表一般包含不止一條記錄, 因此 url 中的名詞一般用複數。api
這些是我參考的資料中,我以爲有趣或專業的幾篇:
相比 REST,api 設計在 2015 年又出了套更有革命意義的理論 GraphQL,基本思路是在前、後端間放一箇中間服務器,而後定義一種查詢語言讓前端描述所需數據,中間服務器接收前端發來的查詢進行解析, 而後自動請求對應的接口並整理數據後再返回給前端,好處是前端獲取數據時不用請求多個接口,一次搞定,也不用記接口路由、參數,這些東西前端都不用管,只管查就是了, 提及來就是個相似 sql 的東西,很方便,詳情能夠看這兩篇文章:REST 將會過期, 而 GraphQL 則會長存、REST 2.0 在此,它的名字叫 GraphQL
RPC 以動詞爲中心,RESTful 以名詞爲中心。
加入新功能時,以動詞爲中心每每必須添加新的動詞,而且後端要實現該動詞,前端要知道這個新的動詞並進行調用; 而以名詞爲中心則沒這麼麻煩,不管要加什麼新功能, 只要沒有添加新的資源,url 是不變的,先後端只需關注各自實現便可,不須要在接口上分心。以名詞爲中心設計 RESTful 風格的接口時,應注意如下幾點:
既然 url 表明資源,那麼進一步,可不可讓 url 更接近 sql?這樣可使接口變得更靈活,基於這點,RESTful api 有了如下這些常見參數:
字段 | 做用 |
---|---|
limit | 指定返回記錄的數量。 |
offset | 指定返回記錄的開始位置。 |
page_number、page_size | 指定第幾頁,以及每頁的記錄數。 |
orderBy、order | 指定返回結果按照哪一個屬性排序,以及排序順序。 |
where | 直接指定 where 條件。 |
id | 指定記錄 id。 |
PS:有些 client 只支持 GET、POST,所以必須由服務端來模擬其它方法,這能夠經過給請求的 header 加上 X-HTTP-Method-Override 字段來實現,它會告訴服務端應該用哪一個方法,例如:
POST /api/Person/4 HTTP/1.1 X-HTTP-Method-Override: PUT
這樣,X-HTTP-Method-Override 就指定該次請求的方法是 PUT,而不是 POST。
爲了保證消息的自描述性,應該使用如下狀態碼來表示常見狀況:
code | 含義 |
---|---|
200(OK) | 請求成功,沒毛病。 |
204(無內容) | 請求成功,但資源爲空。 |
301(Moved Permanently) | 當前資源 URI 已變動。 |
400(bad request) | 無效請求(如參數錯誤) |
404(not found) | 資源不存在。 |
500(internal server error) | 服務器內部錯誤。 |
503(Service Unavailable) | 服務端暫沒法處理請求。 |
接口返回的數據應是 JSON 格式,相應的 response header 的 Content-Type 要設爲 application/json。前端請求時,也應明確告訴服務器接受 JSON 格式,即 request header 的 ACCEPT 要設爲 application/json。JSON 格式並非 RESTful 要求的,只是當下流行的數據傳輸格式,相似不成文規定,之後可能會變。(2019-11-23
API 的使用者未必知道 URL 是如何設計的,所以 RESTful api 還要求資源自描述性。阮一峯博客裏記載的一個解決方法是,在響應數據中給出相關連接。 這樣用戶只要記住一個 URL,就能夠發現其餘 URL。這種方法叫作 HATEOAS。好比 GitHub 的 API 都記載在 api.github.com ,訪問它,就能夠獲得全部 URL, 或者訪問其中一個 URL,返回與其相關的 URL。這樣,用戶不須要記住 URL 設計,只要從 api.github.com 一步步查就能夠了。
RESTful api 能夠很好的實現一套接口,多端使用,很是優秀,但徹底按照它的標準來作我以爲不行,譬如 url 中不能包含動詞這點,動詞單純由 http 方法來提供未免不夠用,有時 api 的做用並不僅是對 資源進行 CURD 四個操做,這就須要更多地動詞,因此我以爲必要時在 url 內加個動詞是很正常的。(並且我仍是喜歡只用 get、post,不想搞那麼多幺蛾子方法,加個動詞又不會死 。。。
另外是參數問題,我看過的技術博客在列舉 RESTful api 時廣泛有相似 /users/123/articles/54 的例子,我以爲改成 /users/articles/123/54 纔是 更合適的作法,這樣後端在定義路由時就能夠寫爲 /users/articles/:userId/:articleId,先路徑,再參數,集中存放,比較舒服。