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