REST 相關介紹和學習資料

轉自:http://hi.baidu.com/zdz8207/blog/item/a0b34c4af3a8e72109f7efc5.html

 

這陣子正打算用Rails做個東東,所以開始系統地學習起了Rails。巧合的是,大概兩週前,dlee邀請我加入Fielding博士關於 REST的那篇論文的翻譯團隊。可以說Rails和REST這兩個最熱門的詞彙幾乎同時擠入了我的生活。隨着我對Rails的學習和對 [Fielding]的翻譯,我也開始對REST產生了一些不太成熟的想法,寫在這裏與大家分享,同時也起到拋磚引玉的作用,歡迎大家討論。

先複習一下REST的基本思想。[Fielding]把REST形式化地定義爲一種架構風格(architecture style),它有架構元素(element)和架構約束(constraint)組成。這些概念比較晦澀難懂,而且我們做工程的往往並不需要形而上的理 解。我們只知道,REST是一種針對網絡應用的設計和開發方式,可以降低開發的複雜性,提高系統的可伸縮性。REST提出了一些設計概念和準則:
1. 網絡上的所有事物都被抽象爲資源(resource);
2. 每個資源對應一個唯一的資源標識(resource identifier);
3. 通過通用的連接器接口(generic connector interface)對資源進行操作;
4. 對資源的各種操作不會改變資源標識;
5. 所有的操作都是無狀態的(stateless)。
對於當今最常見的網絡應用來說,resource identifier是url,generic connector interface是HTTP,第4條準則就是我們常說的url不變性。這些概念中的resouce最容易使人產生誤解。resouce所指的並不是數 據,而是數據+特定的表現形式(representation),這也是爲什麼REST的全名是Representational State Transfer的原因。舉個例子來說,“本月賣得最好的10本書”和“你最喜歡的10本書”在數據上可能有重疊(有一本書即賣得好,你又喜歡),甚至完 全相同。但是它們的representation不同,因此是不同的resource。

REST之所以能夠簡化開發,是因爲其引入的架構約束,比如Rails 1.2中對REST的實現默認把controller中的方法限制在7個:index、show、new、edit、create、update和 destory,這實際上就是對CURD的實現。更進一步講,Rails(也是當今大部分網絡應用)使用HTTP作爲generic connector interface,HTTP則把對一個url的操作限制在了4個之內:GET、POST、PUT和DELETE。

REST之所以能夠提高系統的可伸縮性,是因爲它強制所有操作都是stateless的,這樣就沒有context的約束,如果要做分佈式、做集 羣,就不需要考慮context的問題了。同時,它令系統可以有效地使用pool。REST對性能的另一個提升來自其對client和server任務的 分配:server只負責提供resource以及操作resource的服務,而client要根據resource中的data和 representation自己做render。這就減少了服務器的開銷。

既然REST有這樣的好處,那我們應該義無反顧地擁抱它啊!目前一些大牛(像DHH)都已經開始投入到了REST的世界,那我們這些人應該做什麼或 者說思考寫什麼你呢?我覺得我們應該思考兩個問題:
1. 如何使用REST;
2. REST和MVC的關係。
第一個問題假設REST是我們應該採用的架構,然後討論如何使用;第二個問題則要說明REST和當前最普遍應用的MVC是什麼關係,互補還是取代?

我們先來談談第一個問題,如何使用REST。我感覺,REST除了給我們帶來了一個嶄新的架構以外,還有一個重要的貢獻是在開發系統過程中的一種新 的思維方式:通過url來設計系統的結構。根據REST,每個url都代表一個resource,而整個系統就是由這些resource組成的。因此,如 果url是設計良好的,那麼系統的結構就也應該是設計良好的。對於非高手級的開發人員來說,考慮一個系統如何架構總是一個很抽象的問題。敏捷開發所提倡的 Test Driven Development,其好處之一(我覺得是最大的好處)就是可以通過testcase直觀地設計系統的接口。比如在還沒有創建一個class的時候就 編寫一個testcase,雖然設置不能通過編譯,但是testcase中的方法調用可以很好地從class使用者的角度反映出需要的接口,從而爲 class的設計提供了直觀的表現。這與在REST架構中通過url設計系統結構非常類似。雖然我們連一個功能都沒有實現,但是我們可以先設計出我們認爲 合理的url,這些url甚至不能連接到任何page或action,但是它們直觀地告訴我們:系統對用戶的訪問接口就應該是這樣。根據這些url,我們 可以很方便地設計系統的結構。

讓我在這裏重申一遍:REST允許我們通過url設計系統,就像Test Driven Development允許我們使用testcase設計class接口一樣。

OK,既然url有這樣的好處,那我們就着重討論一下如何設計url。網絡應用通常都是有hierarchy的,像棵大樹。我們通常希望url也能 反映出資源的層次性。比如對於一個blog應用:/articles表示所有的文章,/articles/1表示id爲1的文章,這都比較直觀。遺憾的 是,網絡應用的資源結構永遠不會如此簡單。因此人們常常會問這樣一個問題:RESTful的url能覆蓋所有的用戶請求嗎?比如,login如何 RESTful?search如何RESTful?

從REST的概念上來看,所有可以被抽象爲資源的東東都可以使用RESTful的url。因此對於上面的兩個問題,如果login和search可 以被抽象爲資源,那麼就可以使用RESTful的url。search比較簡單,因爲它會返回搜索結果,因此可以被抽象爲資源,並且只實現index方法 就可以了(只需要顯示搜索結果,沒有create、destory之類的東西)。然而這裏面也有一個問題:search的關鍵字如何傳給 server?index方法顯然應該使用HTTP GET,這會把關鍵字加到url後面,當然不符合REST的風格。要解決這個問題,可以把每次search看作一個資源,因此要創建create和 index方法,create用來在用戶點擊“搜索”按鈕是通過HTTP POST把關鍵字傳給server,然後index則用來顯示搜索結果。這樣一來,我們還可以記錄用戶的搜索歷史。使用同樣的方法,我們也可以對 login應用REST,即每次login動作是一個資源。

現在,我們來複雜一些的東東。如何用url表達“category爲ruby的article”?一開始可能想到的是/category/ruby /articles,這種想法很直觀。但是我覺得裏面的category是不需要的,我們可以直接把“/ruby”理解爲“category是 ruby”,也就是說“ruby”出現的位置說明了它指的就是category。OK,/ruby/articles,單單從這個url上看,我們能獲得 多少關於category的信息呢?顯然category隱藏在了url後面,這樣做到底好不好,應該是仁者見仁,智者見智了。對於如何表達 category這樣的東西,我還沒想出很好的方式,大家有什麼好idea,可以一起討論。

另外還有一種url形式,它對應到程序中的繼承關係。比如product是一個父類,book和computer是其子類。那麼所有產品的url應 該是/products,所有書籍的url應該是/books,所有電腦的url應該是/computers。這一想法就比較直觀了,而且再次驗證了 url可以幫助我們進行設計的論點。

讓我再說明一下我的想法:如果每個用戶需求都可以抽象爲資源,那麼就可以完全使用REST。

由此看來,使用REST的關鍵是如何抽象資源,抽象得越精確,對REST的應用就越好。因此,如何改變我們目前根深蒂固的基於action的思想是 最重要的。

有了對第一個問題的討論,第二個問題就容易討論多了。REST會取代MVC嗎?還是彼此是互補關係(就像AOP對於OOP)?答案是It depends!如果我們可以把所有的用戶需求都可以抽象爲資源,那麼MVC就可以推出歷史的舞臺了。如果情況相反,那麼我們就需要混合使用REST和 MVC。

當然,這是非常理想的論斷。可能我們無法找到一種方法可以把所有的用戶需求都抽象爲資源,因爲保證這種抽象的完整性(即真的是所有需求都可以)需要 形式化的證明。而且即使被證明出來了,由於開發人員的能力和喜好不同,MVC肯定也會成爲不少人的首選。但是對於希望擁抱REST的人來說,這些都沒有關 系。只要你開發的系統所設計的問題域可以被合理地抽象爲資源,那麼REST就會成爲你的開發利器。

所以,所有希望擁抱REST的朋友們,趕快訓練自己如何帶上資源的眼鏡看世界吧,這纔是REST的核心所在。


robbin以前說過REST能讓代碼減少到很少的程度(具體到多少忘了)。現在看來似乎有點言過其實。REST遠沒有想像中的那麼強大。在我看來,如果 採用純REST架構的話,所謂的resource就是經過閹割的OO模型,只有屬性,沒有行爲。爲了表現這些被切掉的行爲,我必須憑空再造出一個個所謂的 resource來,切掉的行爲越多,要造的就越多。這樣的話,代碼不可能有數量級的減少。再想一下,僅僅爲了漂亮的URL,放棄自然和符合人類思維習慣 的OO模型,這樣真的值嗎。套用T1同學的話來說:辛辛苦苦幾十年,一夜回到瞭解放前。
所以我認爲,REST只是在異構系統之間的webservice通訊上有優勢,其他時候,還是該匝地匝地比較好。
--------------------------------------------------------------------
但是我覺得REST有點類似於把數據庫table直接暴露出來的意思,而把應用邏輯編程任務交給了調用者。靈活是靈活,但實際上只是轉移了代碼的位置,而 不是把它們封裝在下面。一個(或一組)應用是否合適使用REST,還是要看具體情況。
目前RoR的REST實現實際上就是REST和MVC混合方式,從實際開發角度來說,正如作者所言,很多情況難以進行資源的抽象。不過,即便如此,已經足 夠有革命性的意義了。

我覺得Rails採用REST混合MVC來實現REST是目前的必然選擇。我們大家都已經熟悉了OO和MVC,對於REST這樣一個新鮮事物,肯定 會帶着以前的眼鏡去看。隨着時間的推移,REST的思想和應用會逐步成熟,人們對其理解也會越來越深刻。到那時才能真正看出REST能不能、如何完全走出 MVC。
我們在使用UP開發方法時,往往需要識別系統的model和use case。有些書中教我們把用戶需求中的名詞抽象爲use case,而動詞則是use case。現在對REST建模有着同樣的問題:我們可以很直觀地把名詞抽象爲resource,但是很難處理動詞。而MVC恰恰適合於處理動詞。這也許就 應了一個老生長談的思想,沒有什麼技術是可以覆蓋所有方面的,只有適當地混合使用各種技術、揚長避短,纔會獲得最好的效果。
REST與Ajax的結合也是個很吸引人的話題,試想由RESTful的服務端API與客戶端的ajax技術的相互調用,能夠產生什麼樣的場景?很想聽聽 大牛的看法。
目前我還想想不出REST加Ajax會產生什麼樣令人震撼的場景。REST的核心是resource,而我覺得對resource的操作最後肯定是通過傳 統HTTP請求發送到server端的。比如寫一篇blog文章,無論如何利用Ajax,最後應該用傳統的HTTP POST請求發送到server以便保存。
REST和Ajax的一個比較有趣的關係是,Ajax也許可以幫助我們解決resource難以建模的問題。就像我說過的那樣,對名詞的抽象很直觀,但是 動詞就比較難辦。而Ajax正好可以用來處理這些動詞,同時保證url不變。當然,如何使用Ajax處理這些動詞也是一個可以討論的話題,我這裏只是說有 這個可能性。不過話說回來,即便使用Ajax處理動詞的話,如何設計Ajax請求所發送到的url仍然是一個問題。目前來看,最可能的設計還是MVC形式 的。所以一個可能的測量是:對所有名詞使用REST架構,對動詞儘量使用Ajax實現的MVC。這樣至少可以保證url看起來是RESTful的。

 

 

理解REST軟件架構
一種思維方式影響了軟件行業的發展。REST軟件架構是當今世界上最成功的互聯網的超媒體分佈式系統。它讓人們真正理解我們的網絡協議HTTP本來面貌。 它正在成爲網絡服務的主流技術,同時也正在改變互聯網的網絡軟件開發的全新思維方式。AJAX技術和Rails框架把REST軟件架構思想真正地在實際中 很好表現出來。今天微軟也已經應用REST並且提出把我們現有的網絡變成爲一個語義網,這種網絡將會使得搜索更加智能化。
REST與HTTP協議
REST軟件架構是由Roy Thomas Fielding博士在2000年首次提出的。他爲我們描繪了開發基於互聯網的網絡軟件的藍圖。REST軟件架構是一個抽象的概念,是一種爲了實現這一互 聯網的超媒體分佈式系統的行動指南。利用任何的技術都可以實現這種理念。而實現這一軟件架構最著名的就是HTTP協議。通常我們把REST也寫作爲 REST/HTTP,在實際中往往把REST理解爲基於HTTP的REST軟件架構,或者更進一步把REST和HTTP看作爲等同的概念。
今天,HTTP是互聯網上應用最廣泛的計算機協議。HTTP不是一個簡單的運載數據的協議,而是一個具有豐富內涵的網絡軟件的協議。它不僅僅能夠對於互聯 網資源進行唯一定位,而且還能告訴我們對於該資源進行怎樣運作。這也是REST軟件架構當中最重要的兩個理念。而REST軟件架構理念是真正理解HTTP 協議而形成的。有了REST軟件架構理念出現,才使得軟件業避免了對HTTP協議的片面理解。只有正確的理論指導,才能避免在軟件開發的實際工作過程中少 走彎路。
REST與URI(資源定位)
REST軟件架構之所以是一個超媒體系統,是因爲它可以把網絡上所有資源進行唯一的定位,不管你的文件是圖片、文件Word還是視頻文件,也不管你的文件 是txt文件格式、xml文件格式還是其它文本文件格式。它利用支持HTTP的TCP/IP協議來確定互聯網上的資源。
REST與CRUD原則
REST軟件架構遵循了CRUD原則,該原則告訴我們對於資源(包括網絡資源)只需要四種行爲:創建(Create)、獲取(Read)、更新 (Update)和銷燬(DELETE)就可以完成對其操作和處理了。其實世界萬物都是遵循這一規律:生、變、見、滅。所以計算機世界也不例外。這個原則 是源自於我們對於數據庫表的數據操作:insert(生)、select(見)、update(變)和delete(滅),所以有時候CRUD也寫作爲 RUDI,其中的I就是insert。這四個操作是一種原子操作,即一種無法再分的操作,通過它們可以構造複雜的操作過程,正如數學上四則運算是數字的最 基本的運算一樣。
REST與網絡服務
儘管在Java語言世界中網絡服務目前是以SOAP技術爲主,但是REST將是是網絡服務的另一選擇,並且是真正意義上的網絡服務。基於REST思想的網 絡服務不久的將來也會成爲是網絡服務的主流技術。REST不僅僅把HTTP作爲自己的數據運輸協議,而且也作爲直接進行數據處理的工具。而當前的網絡服務 技術都需要使用其它手段來完成數據處理工作,它們完全獨立於HTTP協議來進行的,這樣增加了大量的複雜軟件架構設計工作。REST的思想充分利用了現有 的HTTP技術的網絡能力。在德國電視臺上曾經出現過一個這樣的五十萬歐元智力題:如何實現網絡服務才能充分利用現有的HTTP協議?該問題給出了四個答 案:去問微軟;WSDL2.0/SOAP1.2;WS-Transfer;根本沒有。這個問題告訴我們HTTP並不是一個簡單的數據傳來傳去的協議,而是 一個聰明的會表現自己的協議,這也許是REST = Representational State Transfer的真正含義。
實際上目前很多大公司已經採用了REST技術作爲網絡服務,如Google、Amazon等。在Java語言中重要的兩個以SOAP技術開始的網絡服務框 架XFire和Axis也把REST作爲自己的另一種選擇。它們的新的項目分別是Apache CXF 和Axis2 。Java語言也制定關於REST網絡服務規範:JAX-RS: Java API for RESTful Web Services (JSR 311)。相信還會出現更多與REST相關的激動人心的信息。
REST與AJAX技術
儘管AJAX技術的出現纔不到兩年時間,但是AJAX技術遵循了REST的一些重要原則。AJAX技術充分利用了HTTP來獲取網絡資源並且實現了 HTTP沒有的對於異步數據進行傳輸的功能。AJAX技術還使得軟件更好地實現分佈性功能,在一個企業內只要一個人下載了AJAX引擎,其它企業內部的人 員,就可以共享該資源了。AJAX技術遵守REST準則的應用程序中簡單和可伸縮的架構,凡是採用AJAX技術的頁面簡潔而又豐富,一個頁面表現了豐富多 彩的形態。
AJAX技術還使用了一種不同於XML格式的JSON文件格式,這個意義在哪裏呢?在REST軟件架構下我們不能對於XML文件進行序列化處理,這樣程序 員必須要使用自己的XML綁定框架。而以序列化的JavaScript對象爲基礎的JSON已經獲得了廣泛認可,它被認爲能以遠比XML更好的方式來序列 化和傳輸簡單數據結構,而且它更簡潔。這對REST是一個極大貢獻和補充。
當前的網絡應用軟件還違背了REST的“無狀態服務器”約束。REST服務器只知道自己的狀態。REST不關心客戶端的狀態,客戶端的狀態自己來管理,這 是AJAX技術的應用之地。通過AJAX技術,可以發揮有狀態網絡客戶機的優勢。而REST的服務器關心的是從所有網絡客戶端發送到服務器操作的順序。這 樣使得互聯網這樣一個巨大的網絡得到有序的管理。
REST與Rails框架
Ruby on Rails框架(簡稱Rails或者Rails框架)是一個基於Ruby語言的越來越流行的網絡應用軟件開發框架。它提供了關於REST最好的支持,也是 當今應用REST最成功的一個軟件開發框架。Rails框架(從版本1.2.x起)成爲了第一個引入REST作爲核心思想的主流網絡軟件開發框架。在 Rails框架的充分利用了REST軟件架構之後,人們更加堅信REST的重要性和必要性。Rails利用REST軟件架構思想對網絡服務也提供了一流的 支持。從最直觀的角度看待REST,它是網絡服務最理想的手段,但是Rails框架把REST帶到了網絡應用軟件開發框架。這是一次飛躍,讓REST的思 想從網絡服務的應用提升到了網絡應用軟件開發。利用REST思想的simply_restful插件已經成爲了Rails框架的核心內容。
REST安全性
我們把現有基於SOAP的網絡服務和基於REST/HTTP網絡服務作個比喻,前者是一種傳統的寄信方式,而後者是現代網絡的電子郵件方式。要是是寄信和 電子郵件都有病毒存在的話,傳統的寄信被送到對方就很危險,而電子郵件是開發的,電子郵件供應商比如Google爲我們檢查了電子郵件是否有病毒。這裏並 不是說明SOAP網絡服務消息包含義病毒,而是說明HTTP是無法處理SOAP信息包究竟好不好,需要額外的軟件工具解決這一問題,包括防火牆也用不上和 管不了。
REST/HTTP網絡服務的信息包可以被防火牆理解和控制。你可以按照操作和鏈接進行過濾信息包,如你可以規定從外部來的只能讀取(GET操作)自己服 務器的資源。這樣對於系統管理員而言使得軟件管理更爲簡單。REST的安全性還可以利用傳輸安全協議SSL/TLS、基本和摘要式認證(Basic und Digest Authentication)。除了這些REST自身的安全性功能外,還可以利用像基於信息的Web Services Security(JSR 155)作爲REST不錯的補充


但是 REST 到底是什麼呢?論文我看不懂,不過找到一篇更簡單易懂的東西:《Building Web Services the REST Way》。
根據這篇文章,我整理了一下我自己對 REST 的理解:
REST 首先只是一種架構樣式,不是一種標準。這點和 Ajax 類似,兩者都是利用現有的成熟技術。
在 REST 的定義中,一個 Web 應用總是使用固定的 URI 向外部世界呈現(或者說暴露)一個資源。
URI 是英文 Uniform Resource Identifier 的縮寫,中文翻譯“通用資源標誌符”。
“通用資源標誌符”是指唯一標識一個資源(xhtml 文件、圖片、css 樣式表)的字符串。當然了,RFC 中定義的 URI 複雜得多,不過我們此處將 URI 想象成一個人的身份證號碼就行了(你不能有兩個同時有效的身份證號碼,一個號碼也不可能同時對應兩個人)。而我們天天掛在嘴邊的 URL 地址就是 URI 的一種表現形式(個人理解,有錯請糾正)。
知道什麼是 URI 後,我們來看一個實際例子:
http://www.example.com/photo/logo 指向 example.com 網站(可以視爲一個 Web 應用)中類型爲 photo,名字爲 logo 的資源。我們用瀏覽器訪問這個 URI,看到的將可能是一個 xhtml 文檔,其中用 <img src=”……” /> 來顯示實際的照片。
http://www.example.com/photo/logo 很容易讓你想到 URL 重寫。事實上,這個地址很可能會在服務器內部處理爲 http://www.example.com/photo.php?name=logo 這樣的地址。photo.php 是服務器端的一個動態腳本文件,根據 name 參數生成 xhtml 文檔返回給瀏覽器。
現在假設我們要獲取這張照片的 XML 文檔。XML 文檔中包含照片的文件名、文件大小、拍攝日期等等信息。也就是說我們要獲取“同一個資源的不同表現形式的數據”。對於這個要求,我們可以很容易的用另一個 URL 地址達到:http://www.example.com/xml/logo
但是,這就違背了“URI 唯一標識一個資源”的定義。如果我們要獲取同一個資源的多種表現形式,那麼就要使用更多的 URL,從而給一個資源指定了多個不同的 URI。
而在 REST 中,不管是獲取照片的 xhtml 文檔還是 XML 文檔,或者照片文件本身,都是用同一個 URI,就是 http://www.example.com/photo/logo
那這是怎麼辦到的呢?Ruby On Rails 中是通過分辨 HTTP Request Header 信息來分辨客戶端是想要取得資源的哪一種表現形式的數據。
當我們用瀏覽器訪問一個網址時,瀏覽器會構造一個 HTTP 請求。這個請求有一個頭信息,其中包括了本次請求接受何種類型的數據。通常瀏覽器發送的 HTTP 請求頭中,Accept 的值都是 */*,也就說接受服務器返回的任何類型的數據。
看到這裏,聰明的傢伙應該知道了。只要我們指定一個特定的 Accept 參數,那麼服務器就可以通過判斷該參數來決定返回什麼類型的數據。所以在一個採用 REST 架構的應用中,要獲取同一個資源的不同表現形式的數據,只需要使用不同的 HTTP 請求頭信息就行了。
如果考慮爲 Web 應用增加 Web Services,這種技術的價值就體現出來了。比如我寫了一個 Delphi 程序,現在只需要構造一個包含 Accept: text/xml 的 HTTP 請求頭,然後將請求發送到 http://www.example.com/photo/logo 就可以了。返回的結果就是一個 XML 文檔,而不是 xhtml 文檔。
因爲我們的 HTTP 請求頭信息有不同的狀態,從而可以獲得不同的數據,所以叫做“具象狀態傳輸”  
—————————————
除了上面的用法,REST 還有進一步的擴展。
我們在 Web 應用中處理來自客戶端的請求時,通常只考慮 GET 和 POST 這兩種 HTTP 請求方法。實際上,HTTP 還有 HEAD、PUT、DELETE 等請求方法。而在 REST 架構中,用不同的 HTTP 請求方法來處理對資源的 CRUD(創建、讀取、更新和刪除)操作:
• POST: 創建
• GET: 讀取
• PUT: 更新
• DELETE: 刪除
經過這樣的一番擴展,我們對一個資源的 CRUD 操作就可以通過同一個 URI 完成了:
http://www.example.com/photo/logo (讀 取)
仍然保持爲 [GET] http://www.example.com/photo/logo
http://www.example.com/photo/logo/create (創 建)
改爲 [POST] http://www.example.com/photo/logo
http://www.example.com/photo/logo/update (更 新)
改爲 [PUT] http://www.example.com/photo/logo
http://www.example.com/photo/logo/delete (刪 除)
改爲 [DELETE] http://www.example.com/photo/logo
從而進一步規範了資源標識的使用。
通過 REST 架構,Web 應用程序可以用一致的接口(URI)暴露資源給外部世界,並提供對資源的操作服務。這對於以資源爲中心的 Web 應用來說非常重要。例如照片共享網站、用戶社區等。
—————————————
Ruby On Rails 1.2 版對 REST 有很好的支持,但要在 PHP 中應用 REST 還需要解決不少問題:
• 如何在服務端判斷 PUT、DELETE 請求方法;
• 如何獲取用 PUT、DELETE 請求方法中傳遞的數據;
• 如何獲取 HTTP 請求頭信息中的 Accept 參數值;
• 如何在瀏覽器端發起 PUT 和 DELETE 請求。
不過我仔細看了 PHP 文檔,我覺得上面幾個問題都是可以解決的。
服務端綜合使用 $_SERVER[’HTTP_ACCEPT’]、$_SERVER[’REQUEST_URI’]、$_SERVER[’REQUEST_METHOD’]、$_SERVER[’QUERY_STRING’] 這些變量應該可以搞定前面三個問題。而第四個問題則可以用 JavaScript 的 XMLHttpRequest 對象來實現。
不過我想 REST 的真正價值在於 Web Services,而不是通過瀏覽器操作的應用程序。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章