RESTful 給個人最大感受就是規範、易懂和優雅,一個結構清晰、易於理解的 API 徹底能夠省去許多無心義的溝通和文檔。而且 RESTful 如今愈來愈流行,html
在開始介紹 RESTful API 以前,先介紹一下 RESTful 架構。api
REST,即Representational State Transfer 的縮寫。意爲 " 表現層狀態轉化 " 。緩存
要理解RESTful架構,最好的方法就是去理解 Representational State Transfer 這個詞組究竟是什麼意思,它的每個詞表明瞭什麼涵義。若是把這個名稱搞懂了,也就不難體會 REST 是一種什麼樣的設計。服務器
REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"。網絡
所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它能夠是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的實在。你能夠用一個 URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要獲取這個資源,訪問它的 URI 就能夠,所以 URI 就成了每個資源的地址或獨一無二的識別符。所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的 URI 。架構
"資源"是一種信息實體,它能夠有多種外在表現形式。咱們把"資源"具體呈現出來的形式,叫作它的"表現層"(Representation)。
好比,文本能夠用 txt 格式表現,也能夠用 HTML 格式、 XML 格式、JSON 格式表現,甚至能夠採用二進制格式;圖片能夠用 JPG 格式表現,也能夠用 PNG 格式表現。
URI 只表明資源的實體,不表明它的形式。嚴格地說,有些網址最後的" .html "後綴名是沒必要要的,由於這個後綴名錶示格式,屬於"表現層"範疇,而 URI 應該只表明"資源"的位置。它的具體表現形式,應該在 HTTP 請求的頭信息中用 Accept 和 Content-Type 字段指定,這兩個字段纔是對"表現層"的描述。性能
訪問一個網站,就表明了客戶端和服務器的一個互動過程。在這個過程當中,勢必涉及到數據和狀態的變化。
互聯網通訊協議 HTTP 協議,是一個無狀態協議。這意味着,全部的狀態都保存在服務器端。所以,若是客戶端想要操做服務器,必須經過某種手段,讓服務器端發生"狀態轉化"(State Transfer)。而這種轉化是創建在表現層之上的,因此就是"表現層狀態轉化"。
客戶端用到的手段,只能是HTTP協議。具體來講,就是HTTP協議裏面,四個表示操做方式的動詞:GET 、 POST 、 PUT 、 DELETE 。 它們分別對應四種基本操做: GET 用來獲取資源, POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。網站
總結一下什麼是RESTful架構:加密
介紹完 RESTful 的含義,再說說 RESTful API 的設計。設計
若是能全站 HTTPS 固然是最好的,不能的話也請儘可能將登陸、註冊等涉及密碼的接口使用 HTTPS。
應該儘可能將API部署在專用域名之下。如:
https://api.example.com
若是肯定API很簡單,不會有進一步擴展,能夠考慮放在主域名下。
https://example.org/api/
API 的版本號和客戶端 APP 的版本號是毫無關係的,不要讓 APP 將它們用於提交應用市場的版本號傳遞到服務器,而是提供相似於v一、v2之類的 API 版本號。
版本號拼接在 URL 中。如:
api.example.com/v1/users
或是放在 Header 中:
api.xxx.com/users version=v1
通常來講 API 的外在形式無非就是增刪改查(固然具體的業務邏輯確定要複雜得多),而查詢又分爲詳情和列表兩種,在 RESTful 中這就至關於通用的模板。例如針對文章(Article)設計 API,那麼最基礎的 URL 就是這幾種:
GET /articles
: 文章列表GET /articles/id
:文章詳情POST /articles/
: 建立文章PUT /articles/id
:修改文章DELETE /articles/id
:刪除文章API 須要設計成無狀態,因此客戶端在每次請求時都須要提供有效的 Token 和 Sign,在我看來它們的用途分別是:
在 RESTful 的標準中,PUT 和 PATCH 均可以用於修改操做,它們的區別是 PUT 須要提交整個對象,而 PATCH 只須要提交修改的信息。可是在我看來實際應用中不須要這麼麻煩,因此我一概使用 PUT,而且只提交修改的信息。
另外一個問題是在 POST 建立對象時,究竟該用表單提交更好些仍是用 JSON 提交更好些。其實二者均可以,在我看來它們惟一的區別是 JSON 能夠比較方便的表示更爲複雜的結構(有嵌套對象)。另外不管使用哪一種,請保持統一,不要二者混用。
還有一個建議是最好將過濾、分頁和排序的相關信息全權交給客戶端,包括過濾條件、頁數或是遊標、每頁的數量、排序方式、升降序等,這樣可使 API 更加靈活。可是對於過濾條件、排序方式等,不須要支持全部方式,只須要支持目前用得上的和之後可能會用上的方式便可,並經過字符串枚舉解析,這樣可見性要更好些。例如:
搜索,客戶端只提供關鍵詞,具體搜索的字段,和搜索方式(前綴、全文、精確)由服務端決定:
/users/?query=ScienJus
過濾,只須要對已有的狀況進行支持:
/users/?gender=1
分頁:
/users/?page=2&pre_page=20
儘可能使用 HTTP 狀態碼,經常使用的有:
可是有些時候僅僅使用 HTTP 狀態碼沒有辦法明確的表達錯誤信息,因此也能夠在裏面再包一層自定義的返回碼,例如:
成功時:
{ "code": 100, "msg": "成功", "data": {} }
{ "code": -1000, "msg": "用戶名或密碼錯誤" }
data是真正須要返回的數據,而且只會在請求成功時才存在,msg只用在開發環境,而且只爲了開發人員識別。客戶端邏輯只容許識別code,而且不容許直接將msg的內容展現給用戶。若是這個錯誤很複雜,沒法使用一段話描述清楚,也能夠在添加一個doc字段,包含指向該錯誤的文檔的連接。
JSON 比 XML 可視化更好,也更加節約流量,因此儘可能不要使用 XML。
建立和修改操做成功後,須要返回該資源的所有信息。
返回數據不要和客戶端界面強耦合,不要在設計 API 時就考慮少查詢一張關聯表或是少查詢 / 返回幾個字段能帶來多大的性能提高。而且必定要以資源爲單位,即便客戶端一個頁面須要展現多個資源,也不要在一個接口中所有返回,而是讓客戶端分別請求多個接口。
最好將返回數據進行加密和壓縮,尤爲是壓縮在移動應用中仍是比較重要的。