最近 O’Reilly 搞活動,我就半價買了一本《REST in Practice》(Kindle 版鏈接)。對於 O’Reilly 的書,我通常會對比 O’Reilly 打折后的價錢和 Kindle 版的價格,通常是那家更便宜就在那家買,但圖表或代碼比較多的我就會堅持買 O’Reilly 的版本,因為 PDF 能夠最好地保存這些格式。
回到 REST 的話題上。盡管這個概念 2000 年就被提出來了,2007 年成為了一個熱詞,隨后越來越多的服務都宣稱自己是 RESTful 的,但是到底真么做才是真正的 REST 我從來沒有自習學習過。由於 2007 年的時候 Ruby on Rails 也十分熱門,所以我以為 Rails 風格的 CRUD API 就是 REST 了,同時對於外界關於「什么算是 REST 什么不算是 REST」的爭論沒怎么關心過。
記得之前老趙提到過《REST in Practice》是本好書,所以我就收藏到 wish list 里面了,在 O’Reilly 打折時就下狠心買下來,然后看看爭論得如此多的 REST 到底是什么東東。書中提到 Richardson 的 REST 成熟度模型,通過這個模型你可以理解什么是 REST 什么不是 REST。這個模型是這樣子的:
第 0 級服務:只使用一個 URI 作為一個服務端口,也只使用一個 HTTP 方法傳輸數據。大多數 WS-* 服務都是這個級別的,XML-RPC 和 POX 也是。這種做法相當於把 HTTP 這個應用層協議降級為傳輸層協議用。HTTP 頭和有效載荷是完全隔離的,HTTP 頭只用於保證傳輸,不涉及業務邏輯;有效載荷包含全部業務邏輯,因此 API 可以無視 HTTP 頭中的任何信息。
第 1 級服務:使用多個 URI,不同的 URI 代表不同的調用入口,但只使用同一個 HTTP 方法傳輸數據。
第 2 級服務:使用多個 URI,不同的 URI 代表不同的資源,同時使用多個 HTTP 方法操作這些資源,例如使用 POST/GET/PUT/DELET 分別進行 CRUD 操作。這時候 HTTP 頭和有效載荷都包含業務邏輯,例如 HTTP 方法對應 CRUD 操作,HTTP 狀態碼對應操作結果的狀態。我們現在看到的大多數所謂 RESTful API 做到的也就是這個級別。
第 3 級服務:使用超媒體(hypermedia)作為應用狀態引擎。要解釋這個概念先要解釋什么是超媒體:
我們已經知道什么是多媒體(multimedia),以及什么是超文本(hypertext)。其中超文本特有的優勢是擁有超鏈接(hyperlink)。如果我們把超鏈接引入到多媒體當中去,那就得到了超媒體,因此關鍵角色還是超鏈接。使用超媒體作為應用引擎狀態,意思是應用引擎的狀態變更由客戶端訪問不同的超媒體資源驅動。
舉個例子來說,用戶在論壇的帖子列表點擊超鏈接進入某個帖子,這時候瀏覽器作為一個客戶端就會去 GET 這個帖子的鏈接 URI,應用狀態就切換為顯示某個帖子了。接着用戶輸入回復提交表單,瀏覽器就會根據 form
上面的 action
屬性 POST 內容給目標 URI,應用狀態就再一次發生切換,完成了回復的存儲。
使用超媒體與前面第 1 級、第 2 級的顯著區別是,客戶端不再和 URI 緊耦合。在第 1 級或者第 2 級的應用里面,客戶端都需要知道資源使用的 URI 模版(如 /orders/{id}
),然后要操作什么樣的資源就生成什么樣的 URI。超媒體客戶端只知道入口 URI,之后的每一個 URI 都是通過超鏈接獲得的。
還是用上述論壇例子來解釋,假若這個論壇通過 Atom 協議支持非瀏覽器的客戶端訪問。客戶端是不需要知道論壇帖子的 URI 模版的,因為客戶端可以通過帖子列表的 Atom 獲得帖子的超鏈接,然后在用戶選擇瀏覽帖子時獲取對應 URI 的內容。獲取回來的結果不會帶有 form
,但會帶有 <link rel="reply" />
,通過這個 link
客戶端又知道了用戶提交的回復應該發往哪個 URI。
說完 Richardson 的成熟度模型,說說 REST 這篇論文作者 Roy Fielding 的回應。Roy Fielding 說「只有使用了超媒體的才能算是 REST」。簡單來說,他認為第 3 級成熟度以外的都不算 REST。我個人的看法是,我支持 Roy Fielding 對 REST 的嚴格定義,我也認為一個真正使用了超媒體實現應用狀態引擎的服務非常了不起,但是在普通 CRUD API 能滿足需求的情況下我覺得使用 CRUD API 也可以。
這本書后面還講到了如何使用緩存來增加系統健壯性,如何使用 Atom 和 Atom 發布協議,如何使用 OpenID 和 OAuth 等認證授權技術。因為這本書我還沒看完,所以這些內容我也不好做評價。
這本書總體來說寫得不錯,但就是廢話稍微多了一點點。如果你跳着章節地去看,可能就不會覺得那是廢話了,因為你挑選出來閱讀的部分都包含所有的信息。但如果你像我這樣從頭到尾地閱讀,就會覺得作者怎么前面提到過的事情后面還要再提及。
此外這本書提供的大量 .NET 和 Java 代碼對我來說沒什么意義。我覺得這本書更多是寫給做企業服務的人看的,希望他們的思維模式能夠從企業環境里常見的 WS-* 跳出來,同時希望證明給他們看實現 REST 是多么簡單的事情。這對於天天研究互聯網服務的我來說沒什么必要,況且我也很久沒寫過 .NET 代碼了,所以各式各樣的示例代碼給我無視掉了。我覺得我知道這件事情 WCF 能做也就足夠了。