REST(Representational State Transfer) 是Roy Thoms Fielding在其博士論文中所提出的一種架構風格(Architectual Style)。
http://roy.gbiv.com/pubs/dissertation/top.htm http://www.redsaga.com/opendoc/REST_cn.pdf 可以說它也體現了整個互聯網架構的基本設計原則。隨著AJAX等技術的發展,互聯網的資源語義逐漸得以恢復,最近對于REST的討論也熱烈起來。
http://www.ibm.com/developerworks/cn/web/wa-ajaxarch/ 在Fielding的論文中對REST有如下陳述:
The name “Representational State Transfer” is intended to evoke an image of how a well-designed
Web application behaves: a network of web pages (a virtual state-machine), where the
user progresses through the application by selecting links (state transitions), resulting in
the next page (representing the next state of the application) being transferred to the user
and rendered for their use.
點擊超鏈接之后,服務器端返回資源的某種表示(Resource Representation), 客戶端的狀態(Representational State)隨之發生遷移(transition),在服務器端返回的表示中存在著到其他狀態的遷移鏈接,使得我們始終自動具有進一步遷移的能力(這和ajax中所謂返回純粹數據其實是不同的). 這種圖景其實也正是Tim Berners-Lee最早所設想的web的圖景。因為REST是對互聯網架構設計的一種抽象,因此所謂的Restful其實就是盡量符合現有Web標準。從概念上說,REST所關注的主要還是分布式資源信息交換,而不是對復雜的業務邏輯進行抽象。遵循REST將會使整個互聯網受益,確保路由器,緩存,代理,瀏覽器,服務器等各個組件可以協同工作,它的意義并不是針對單個應用程序的。不過與witrix體系架構相對比,我們還是可以發現REST架構風格對于一般web程序的參考價值。
1. 通過唯一的,確定的url來標定可訪問的資源。url定義了后臺資源的訪問界面,明確區分了瀏覽器和服務器兩個分離的狀態空間。這種兩分的架構約束是witrix平臺最重要的設計原則。在witrix平臺中,Jsplet, BizFlow, PageFlow,AuthMap等技術完全體現在url的精化設計上,系統中所涉及到的所有關鍵概念都對應于url中的明確組分。而JSF等技術通過對象封裝模糊了資源的訪問界面,迫使我們只能通過一個錯綜復雜的對象包絡來理解系統的交互過程。
2. REST強調整個交互圖景中所有需要的相關信息都是in band的,而且語義上不同的部分都對應于特定的語法上不同的部分。例如為了保證url的不透明性和穩定性,一些信息通過http協議的header來傳遞。這里強調的語義自明性實際上是脫離具體知識體系的形式上的可區分性。在現有的服務器端程序中, 因為直接接觸到的是已經解析好的parameter集合, 因此Witrix平臺中關注的是在參數集合中識別出特定的形式結構, 這通過EngineURL對象實現.
3. HTTP中明確區分了GET/POST/PUT/DELETE四種標準操作, 并對它們的語義進行了精確的限定. 而所謂的RPC(Remote Procedure Call)與此是不同的. RPC上承載的方法數可以是無限多的,但是這種無限多的操作反而從某種層面上說是簡單的,是對稱的,沒有可區分性。而在REST中,在確定資源這一限制下,我們可以區分出GET/POST/DELETE/PUT這四種有限但是不同的語義。 是否這四種語義構成完備的操作空間?從某種意義上說, 這四種操作覆蓋了資源的整個生命周期, 它自然滿足了某種完備性. 但是抽象意義上的完備性并不意味著它在物理層面上也是完備的. 我們都知道二維空間是完備的,但是二維描述并不是三維空間的合適表達. 在Witrix體系下,WebAction所提供的完備的操作集合包括Query, ViewDetail, Update, Add和BizAction.
BizAction是個特定的擴展,所有不便于直接歸類到CRUD操作的操作都可以歸類到這一Action的名義下. Witrix架構中把CRUD看作是一個更大的Action空間的一個子空間, 對此子空間的結構進行了細致的劃分, 所關注的重點是對部分信息的更明確的表達, 而不是對程序整體的建模.
區分GET/POST/PUT/DELETE四種操作, 最重要的意義在于定義了GET和其他操作的區別.
http://www.w3.org/DesignIssues/Axioms.html a. in HTTP, GET must not have side effects
b. in HTTP, anything which does not have side-effects should use GET
在GET這種語義下, 才可能建立獨立的cache組件, 而正是因為cache的存在, 才使得web成為infomation space而不是computing program. 而在Witrix平臺中, 很多通用機制的建立(例如精確到數據行的訪問權限)都需要對于CRUD做出精細的區分, 而不僅僅是識別出GET操作.
4. REST中雖然定義了具有概念穩定性的url, 但是因為操作集合有限,而且強調服務器端的無狀態性, 因此一般認為這種結構并不是面向對象的. 不過,在我看來,面向對象首先意味著一組相關性的聚集, 實際上從語義層面上看, REST與witrix平臺的jsplet框架非常接近, 最大的差別在于服務器端明確定義的thisObj---this指針. 服務器端的無狀態性對于網站應用而言是必要的, 但是對于復雜的企業應用而言并不是合適的約束.
5. 對整個互聯網應用而言,URI應該是不透明的,它的結構對互聯網中間應用而言應該是不暴露的. 資源的結構是與整個互聯網架構無關的. 最近業內鼓吹REST的時候往往也推崇所謂beautify的url, 例如 http://www.my.com/blog/3/comment/1. 這種結構不過是維護url穩定性的一種副產品, 在我看來, 它對于REST而言并不是必需的. 不過根據這些年關系數據庫應用積累的經驗,識別集合和集合中的個體是一種非常通用的場景,因此我們可能規范化這種結構,甚至搜索引擎等外部組件也可能理解這種語義,從而實現更加復雜的語義網絡。在現有的所謂支持REST的web框架中, 往往支持這種規范化的url直接映射到后臺的響應函數上.
https://cetia4.dev.java.net/files/documents/5545/38989/cetia4_tutorial.pdf. 例如在cetia4框架中, GET /blog/3將會被映射到后臺函數 String render(RenderContext context, int id)函數上. 在witrix平臺中, 缺省并不采用beautify的url, 但是因為對于語法成分具有明確的定義, objectEvent=ViewDetail&id=3這樣的url將映射到后臺biz-flow中的action段.
<action id="ViewDetail-default">
<source>
在這里直接拿到entity對象,而不是id值
</source>
</action>
在action中我們直接接觸到的不是id值,而是id值相對應的實體對象本身. 對于objectEvent=Remove, 我們可能一次刪除多條記錄, 則在后臺bizflow中action=Remove-default段將會被調用多次,每次處理一個實體. 這些自動處理機制都離不開對于標準化url組分的明確理解.
在網站應用中, 我們一般也通過url rewrite機制來支持簡化的層級url. 但是這種根據位置來確定語義成分的url格式其實也存在著很大的局限性, 在cetia4的映射中很多時候都會出現含混的情況. 而且因為資源是抽象的, 頁面中的相對路徑計算會出現一定的困難. 在witrix平臺中, 通過tpl模板語言的標簽增強機制, 我們重新定義了頁面中的相對路徑計算規則, 從而大大簡化了資源管理問題. 在tpl中相對路徑計算永遠是基于當前模板文件的, 例如對于通過<c:include src="subdir/included.tpl" />引入的子頁面included.tpl, 在其中的<script src="included.js" />等使用相對路徑的語句會在編譯期被轉換為使用絕對路徑, 生成<script src="/contextPath/root/subdir/included.js" >等語句.
6. 一旦url格式被規范化, 我們就可以基于它在應用程序中發展很多全局結構. 例如在cetia4中, 可以建立全局的navigation模型, 并提供了一個breadcrumb 導航欄. 這是一種全局的鏈接管理機制,在一定程度上實現了導航信息壓縮. 但是因為其沒有對象結構支撐, 與Witrix平臺的PageFlow技術相比, cetia4的方式不過是非常原始的一級策略, 它對于對象生命周期的管理也是過于簡陋的.http://canonical.javaeye.com/blog/32552
7. REST中強調generic interface 而不是強調custom interface. 實際上目前業內的對象化方案很多時候都沉迷于提供特定結構的構造方法, 很多面向對象框架本身就在構造各式各樣的特定結構。一種通用的結構只存在于概念中,是復雜結構背后的事情。但是在很多情況下, generic interface無論在實現成本還是概念成本上都是更加低廉的. 在witrix平臺中, jsplet框架所實現的對象化就是一種generic方式的,弱類型化的, 而不是強類型的對象結構的。
8. 關于REST的另一個有趣的問題是如果大量使用HTTP內置特性,是否我們的應用將嚴格綁定到http協議上,不再是所謂的protocol independence。不過我們真的需要同一語義模型的不同實現嗎.