表現層狀態轉換
表現層狀態轉換(英語:Representational State Transfer,縮寫:REST)是Roy Thomas Fielding博士於2000年在他的博士論文[1]中提出來的一種萬維網軟件架構風格,目的是便於不同軟件/程式在網絡(例如互聯網)中互相傳遞資訊。表現層狀態轉換根基於超文字傳輸協定,是一種軟件架構。符合或相容於這種架構風格(簡稱為 REST 或 RESTful)的網絡服務,用戶端在發出存取和操作網絡資源的請求時可以發出統一資源識別碼。表現層狀態轉換提供了在互聯網絡的計算系統之間,彼此資源可互動使用的協作性質(interoperability)。相對於其它種類的網絡服務,例如SOAP服務,則是以本身所定義的操作集,來存取網絡上的資源。
目前在三種主流的Web服務實現方案中,因為REST模式與複雜的SOAP和XML-RPC相比更加簡潔,越來越多的Web服務開始採用REST風格設計和實現。例如,Amazon.com提供接近REST風格的Web服務執行圖書查詢;Yahoo提供的Web服務也是REST風格的。
要點及標準
[編輯]需要注意的是,REST是設計風格而不是標準。REST通常基於HTTP、URI、XML以及HTML這些現有的廣泛流行的協定和標準。
- 資源是由URI來指定。
- 對資源的操作包括取得、建立、修改和刪除,這些操作正好對應HTTP協定提供的GET、POST、PUT和DELETE方法。
- 透過操作資源的表現形式來操作資源。
- 資源的表現形式則是XML或者HTML,取決於讀者是機器還是人、是消費Web服務的客戶軟件還是Web瀏覽器。當然也可以是任何其他的格式,例如JSON。
表示狀態傳送的特徵
[編輯]- Uniform Interface:統一介面。
- 以資源為基礎
每個資源都可以透過URI訪問到。
也就是一個個可以認知的資源,比如文件,音樂,影片等資訊,都可以透過唯一的URI確定。
- 透過重表達的客戶端可以管理原資源
就是我們透過客戶端可以修改原資源的狀態。
- 返回資訊足夠描述自己
這樣重表達的客戶端可以知道如何處理。
- 超媒體是應用狀態的引擎
處理以超媒體為基礎的狀態變化。
- 以資源為基礎
- Stateless:無狀態。
- Cacheable:可快取。
- Client-Server:客戶伺服器分離模式,任何一個客戶端與伺服器都是可替換的。
- Layered System:分層的系統,客戶端不知道他聯絡的是不是最終伺服器。
- Code on Demand(可選):伺服器可以將能力擴充到客戶端,如果客戶端可以執行的話。這個功能是可選擇的。
REST架構的限制條件
[編輯]REST架構風格最重要的架構限制有6個[2]:
- 客戶端-伺服器(Client-Server)
- 客戶端-伺服器結構限制的目的是將客戶端和伺服器端的關注點分離。將用戶介面所關注的邏輯和數據儲存所關注的邏輯分離開來有助於提高用戶介面的跨平台的可移植性。透過簡化伺服器模組也有助於伺服器模組的可延伸性。
- 無狀態(Stateless)
- 伺服器不能儲存客戶端的資訊;每一次從客戶端傳送的請求中,要包含所有的必須的狀態資訊,對談資訊由客戶端儲存,伺服器端根據這些狀態資訊來處理請求。
- 伺服器可以將對談狀態資訊傳遞給其他服務,比如資料庫服務,這樣可以保持一段時間的狀態資訊,從而實現認證功能。
- 當客戶端可以切換到一個新狀態的時候傳送請求資訊。
- 當一個或者多個請求被傳送之後,客戶端就處於一個狀態變遷過程中。每一個應用的狀態描述可以被客戶端用來初始化下一次的狀態變遷。
- 快取(Cacheability)
- 如同萬維網一樣,客戶端和中間的通訊傳遞者可以將回覆快取起來。回覆必須明確的或者間接的表明本身是否可以進行快取,這可以預防客戶端在將來進行請求的時候得到陳舊的或者不恰當的數據。管理良好的快取機制可以減少客戶端-伺服器之間的互動,甚至完全避免客戶端-伺服器互動,這進一步提了高效能和可延伸性。
- 統一介面(Uniform Interface)
- 這是 RESTful 系統設計的基本出發點。它簡化了系統架構,減少了耦合性,可以讓所有模組各自獨立的進行改進。包括下列四個限制:
- 請求中包含資源的 ID(Resource identification in requests)
請求中包含了各種獨立資源的標識,例如,在Web服務中的URI。資源本身和傳送給客戶端的標識是獨立。例如,伺服器可以將自身的資料庫資訊以HTML、XML或者JSON的方式傳送給客戶端,但是這些可能都不是伺服器的內部記錄方式。
- 資源透過標識來操作(Resource manipulation through representations)
當客戶端擁有一個資源的標識,包括附帶的元數據,則它就有足夠的資訊來刪除這個資源。
- 訊息的自我描述性(Self-descriptive messages)
每一個訊息都包含足夠的資訊來描述如何來處理這個資訊. 例如,媒體類型 (media-type) 就可以確定需要什麼樣的剖析器來分析媒體數據.
- 用超媒體驅動應用狀態(Hypermedia as the engine of application state (HATEOAS))
同用戶訪問Web伺服器的Home頁面相似,當一個 REST 客戶端訪問了最初的REST應用的URI之後,REST 客戶端應該可以使用伺服器端提供的連結,動態的發現所有的可用的資源和可執行的操作。隨着訪問的進行,伺服器在響應中提供文字超連結,以便客戶端可以得到當前可用的操作。客戶端無需用確定的編碼的方式記錄下伺服器端所提供的動態應用的結構資訊。
- 請求中包含資源的 ID(Resource identification in requests)
- 這是 RESTful 系統設計的基本出發點。它簡化了系統架構,減少了耦合性,可以讓所有模組各自獨立的進行改進。包括下列四個限制:
- 分層系統(Layered System)
- 客戶端一般不知道是否直接連接到了最終的伺服器,或者是路徑上的中間伺服器。中間伺服器可以透過負載均衡和共用快取的機制提高系統的可延伸性,這樣可也便於安全策略的部署。
- 按需代碼(Code-On-Demand,可選)
- 伺服器可以透過傳送可執行代碼給客戶端的方式臨時性的擴充功能或者客製化功能,例如Java Applet、Flash或JavaScript。
關於狀態
[編輯]應該注意區別應用的狀態和連接協定的狀態。HTTP連接是無狀態的(也就是不記錄每個連接的資訊),而REST傳輸會包含應用的所有狀態資訊,因此可以大幅降低對HTTP連接的重複請求資源消耗。
應用於Web服務
[編輯]符合REST設計風格的Web API稱為RESTful API。它從以下三個方面資源進行定義:
- 直觀簡短的資源地址:URI,比如:
http://example.com/resources
。 - 傳輸的資源:Web服務接受與返回的互聯網媒體類型,比如:JSON,XML,YAML等。
- 對資源的操作:Web服務在該資源上所支援的一系列請求方法(比如:POST,GET,PUT或DELETE)。
下表列出了在實現RESTful API時HTTP請求方法的典型用途。
資源 | GET | PUT | POST | DELETE |
---|---|---|---|---|
一組資源的URI,比如https://example.com/resources
|
列出URI,以及該資源組中每個資源的詳細資訊(後者可選)。 | 使用給定的一組資源替換當前整組資源。 | 在本組資源中建立/追加一個新的資源。該操作往往返回新資源的URL。 | 刪除整組資源。 |
單個資源的URI,比如https://example.com/resources/142
|
取得指定的資源的詳細資訊,格式可以自選一個合適的網絡媒體類型(比如:XML、JSON等) | 替換/建立指定的資源。並將其追加到相應的資源組中。 | 把指定的資源當做一個資源組,並在其下建立/追加一個新的元素,使其隸屬於當前資源。 | 刪除指定的元素。 |
PUT和DELETE方法是冪等方法。GET方法是安全方法(不會對伺服器端有修改,因此當然也是冪等的)。
不像基於SOAP的Web服務,RESTful Web服務並沒有「正式」的標準[4]。這是因為REST是一種架構,而SOAP只是一個協定。雖然REST不是一個標準,但大部分RESTful Web服務實現會使用HTTP、URI、JSON和XML等各種標準。
實現舉例
[編輯]例如,一個簡單的網絡商店應用:
- 列舉所有商品:
GET http://www.store.com/products
- 呈現某一件商品:
GET http://www.store.com/products/12345
- 下單購買:
POST http://www.store.com/orders <purchase-order> <item> ... </item> </purchase-order>
REST的優點
[編輯]- 可更高效利用快取來提高響應速度
- 通訊本身的無狀態性可以讓不同的伺服器的處理一系列請求中的不同請求,提高伺服器的擴充性
- 瀏覽器即可作為客戶端,簡化軟體需求
- 相對於其他疊加在HTTP協定之上的機制,REST的軟體相依性更小
- 不需要額外的資源發現機制
- 在軟體技術演進中的長期的相容性更好
實現
[編輯]- Ruby on Rails1.2以後的版本支援REST model (頁面存檔備份,存於互聯網檔案館)。
- JBoss RESTEasyJBoss的REST實現
- Node.js RESTful APINode.js實現RESTful API
- Learn REST: A RESTful Tutorial (頁面存檔備份,存於互聯網檔案館)
參考文獻
[編輯]參照
[編輯]- ^ Fielding, Roy Thomas. Chapter 5: Representational State Transfer (REST). Architectural Styles and the Design of Network-based Software Architectures (學位論文). University of California, Irvine. 2000 [2016-12-29]. (原始內容存檔於2021-05-13).
This chapter introduced the Representational State Transfer (REST) architectural style for distributed hypermedia systems. REST provides a set of architectural constraints that, when applied as a whole, emphasizes scalability of component interactions, generality of interfaces, independent deployment of components, and intermediary components to reduce interaction latency, enforce security, and encapsulate legacy systems.
- ^ 理解RESTful. [2016-03-18]. (原始內容存檔於2018-11-02).
- ^ Richardson, Leonard; Ruby, Sam, RESTful Web Services, O'Reilly, 2007(May 8, 2007), ISBN 0596529260
- ^ Elkstein, M. What is REST? (頁面存檔備份,存於互聯網檔案館). Retrieved on 2009-07-04.
來源
[編輯]- Roy Thomas Fielding的博士論文「Architectural Styles and the Design of Network-based Software Architectures(頁面存檔備份,存於互聯網檔案館)」
- Paul Prescod. 第二代web服務