<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    深入淺出REST

    作者 Stefan Tilkov

    不知你是否意識到,圍繞著什么才是實現異構的應用到應用通信的“正確”方式,一場爭論正進行的如火如荼:雖然當前主流的方式明顯地集中在基于SOAP、 WSDL和WS-*規(guī)范的Web Services領域,但也有少數人用細小但洪亮的聲音主張說更好的方式是REST,表述性狀態(tài)轉移(REpresentational State Transfer)的簡稱。在本文中,我不會涉及爭論的話題,而是嘗試對REST和RESTful HTTP應用集成做實用性的介紹。以我的經驗,有些話題一旦觸及就會引來眾多的討論,當涉及到這方面話題的時候,我會深入詳細地闡述.

    REST關鍵原則

    大部分對REST的介紹是以其正式的定義和背景作為開場的。但這兒且先按下不表,我先提出一個簡單扼要的定義:REST定義了應該如何正確地使用 (這和大多數人的實際使用方式有很大不同)Web標準,例如HTTP和URI。如果你在設計應用程序時能堅持REST原則,那就預示著你將會得到一個使用 了優(yōu)質Web架構(這將讓你受益)的系統(tǒng)。總之,五條關鍵原則列舉如下:

    • 為所有“事物”定義ID
    • 將所有事物鏈接在一起
    • 使用標準方法
    • 資源多重表述
    • 無狀態(tài)通信

    下面讓我們進一步審視這些原則。

    為所有“事物”定義ID

    在這里我使用了“事物”來代替更正式準確的術語“資源”,因為一條如此簡單的原則,不應該被淹沒在術語當中。思考一下人們構建的系統(tǒng),通常會找到一 系列值得被標識的關鍵抽象。每個事物都應該是可標識的,都應該擁有一個明顯的ID——在Web中,代表ID的統(tǒng)一概念是:URI。URI構成了一個全局命 名空間,使用URI標識你的關鍵資源意味著它們獲得了一個唯一、全局的ID。

    對事物使用一致的命名規(guī)則(naming scheme)最主要的好處就是你不需要提出自己的規(guī)則——而是依靠某個已被定義,在全球范圍中幾乎完美運行,并且能被絕大多數人所理解的規(guī)則。想一下你 構建的上一個應用(假設它不是采用RESTful方式構建的)中的任意一個高級對象(high-level object),那就很有可能看到許多從使用唯一標識中受益的用例。比如,如果你的應用中包含一個對顧客的抽象,那么我可以相當肯定,用戶會希望將一個指 向某個顧客的鏈接,能通過電子郵件發(fā)送到同事那里,或者加入到瀏覽器的書簽中,甚至寫到紙上。更透徹地講:如果在一個類似于Amazon.com的在線商 城中,沒有用唯一的ID(一個URI)標識它的每一件商品,可想而知這將是多么可怕的業(yè)務決策。

    當面對這個原則時,許多人驚訝于這是否意味著需要直接向外界暴露數據庫記錄(或者數據庫記錄ID)——自從多年以來面向對象的實踐告誡我們,要將持 久化的信息作為實現細節(jié)隱藏起來之后,哪怕是剛有點想法都常會使人驚恐。但是這條原則與隱藏實現細節(jié)兩者之間并沒有任何沖突:通常,值得被URI標識的事 物——資源——要比數據庫記錄抽象的多。例如,一個定單資源可以由定單項、地址以及許多其它方面(可能不希望作為單獨標識的資源暴露出來)組成。標識所有 值得標識的事物,領會這個觀念可以進一步引導你創(chuàng)造出在傳統(tǒng)的應用程序設計中不常見的資源:一個流程或者流程步驟、一次銷售、一次談判、一份報價請求—— 這都是應該被標識的事物的示例。同樣,這也會導致創(chuàng)建比非RESTful設計更多的持久化實體。

    下面是一些你可能想到的URI的例子:

    http://example.com/customers/1234
    http://example.com/orders/2007/10/776654
    http://example.com/products/4554
    http://example.com/processes/salary-increase-234

    正如我選擇了創(chuàng)建便于閱讀的URI——這是個有用的觀點,盡管不是RESTful設計所必須的——應該能十分容易地推測出URI的含義:它們明顯地標識著單一“數據項”。但是再往下看:

    http://example.com/orders/2007/11
    http://example.com/products?color=green

    首先,這兩個URI看起來與之前的稍有不同——畢竟,它們不是對一件事物的標識,而是對一類事物集合的標識(假定第一個URI標識了所有在2007年11月份提交的定單,第二個則是綠顏色產品的集合)。但是這些集合自身也是事物(資源),也應該被標識。

    注意,使用唯一、全局統(tǒng)一的命名規(guī)則的好處,既適用于瀏覽器中的Web應用,也適用于機對機(machine-to-machine,m2m)通信。

    來對第一個原則做下總結:使用URI標識所有值得標識的事物,特別是應用中提供的所有“高級”資源,無論這些資源代表單一數據項、數據項集合、虛擬亦或實際的對象還是計算結果等。

    將所有事物鏈接在一起

    接下來要討論的原則有一個有點令人害怕的正式描述:“超媒體被當作應用狀態(tài)引擎(Hypermedia as the engine of application state)”,有時簡寫為HATEOAS。(嚴格地說,這不是我說的。)這個描述的核心是超媒體概念,換句話說:是鏈接的思想。鏈接是我們在HTML中常見的概念,但是它的用處絕不局限于此(用于人們網絡瀏覽)。考慮一下下面這個虛構的XML片段:

     
    23


    如果你觀察文檔中product和customer的鏈接,就可以很容易地想象到,應用程序(已經檢索過文檔)如何“跟隨”鏈接檢索更多的信息。當然,如果使用一個遵守專用命名規(guī)范的簡單“id”屬性作為鏈接,也是可行的——但是僅限于應用環(huán)境之內。使用URI表示鏈接的優(yōu)雅之處在于,鏈接可以指向由不同應用、不同服務器甚至位于另一個大陸上的不同公司提供的資源——因為URI命名規(guī)范是全球標準,構成Web的所有資源都可以互聯互通。

    超媒體原則還有一個更重要的方面——應用“狀態(tài)”。簡而言之,實際上服務器端(如果你愿意,也可以叫服務提供者)為客戶端(服務消費者)提供一組鏈 接,使客戶端能通過鏈接將應用從一個狀態(tài)改變?yōu)榱硪粋€狀態(tài)。稍后我們會在另一篇文章中探究這個方面的影響;目前,只需要記住:鏈接是構成動態(tài)應用的非常有 效的方式。

    對此原則總結如下:任何可能的情況下,使用鏈接指引可以被標識的事物(資源)。也正是超鏈接造就了現在的Web。

    使用標準方法

    在前兩個原則的討論中暗含著一個假設:接收URI的應用程序可以通過URI明確地一些有意義的事情。如果你在公共汽車上看到一個URI,你可以將它輸入瀏覽器的地址欄中并回車——但是你的瀏覽器如何知道需要對這個URI做些什么呢?

    它知道如何去處理URI的原因在于所有的資源都支持同樣的接口,一套同樣的方法(只要你樂意,也可以稱為操作)集合。在HTTP中這被叫做動詞 (verb),除了兩個大家熟知的(GET和POST)之外,標準方法集合中還包含PUT、DELETE、HEAD和OPTIONS。這些方法的含義連同 行為許諾都一起定義在HTTP規(guī)范之中。如果你是一名OO開發(fā)人員,就可以想象到RESTful HTTP方案中的所有資源都繼承自類似于這樣的一個類(采用類Java、C#的偽語法描述,請注意關鍵的方法):

    class Resource {
    Resource(URI u);
    Response get();
    Response post(Request r);
    Response put(Request r);
    Response delete();
    }

    由于所有資源使用了同樣的接口,你可以依此使用GET方法檢索一個表述(representation)——也 就是對資源的描述。因為規(guī)范中定義了GET的語義,所以可以肯定當你調用它的時候不需要對后果負責——這就是為什么可以“安全”地調用此方法。GET方法 支持非常高效、成熟的緩存,所以在很多情況下,你甚至不需要向服務器發(fā)送請求。還可以肯定的是,GET方法具有冪等性[譯 注:指多個相同請求返回相同的結果]——如果你發(fā)送了一個GET請求沒有得到結果,你可能不知道原因是請求未能到達目的地,還是響應在反饋的途中丟失了。 冪等性保證了你可以簡單地再發(fā)送一次請求解決問題。冪等性同樣適用于PUT(基本的含義是“更新資源數據,如果資源不存在的話,則根據此URI創(chuàng)建一個新 的資源”)和DELETE(你完全可以一遍又一遍地操作它,直到得出結論——刪除不存在的東西沒有任何問題)方法。POST方法,通常表示“創(chuàng)建一個新資 源”,也能被用于調用任過程,因而它既不安全也不具有冪等性。

    如果你采用RESTful的方式暴露應用功能(如果你樂意,也可以稱為服務功能),那這條原則和它的約束同樣也適用于你。如果你已經習慣于另外的設計方式,則很難去接受這條原則——畢竟,你很可能認為你的應用包含了超出這些操作表達范圍的邏輯。請允許我花費一些時間來讓你相信不存在這樣的情況。

    來看下面這個簡單的采購方案例子:

    Sample Scenario

    可以看到,例子中定義了兩個服務程序(沒有包含任何實現細節(jié))。這些服務程序的接口都是為了完成任務(正是我們討論的 OrderManagement和CustomerManagement服務)而定制的。如果客戶端程序試圖使用這些服務,那它必須針對這些特定接口進行 編碼——不可能在這些接口定義之前,使用客戶程序去有目的地和接口協(xié)作。這些接口定義了服務程序的應用協(xié)議(application protocol)。

    在RESTful HTTP方式中,你將通過組成HTTP應用協(xié)議的通用接口訪問服務程序。你可能會想出像這樣的方式:

    Sample Scenario, done RESTfully

    可以看到,服務程序中的特定操作被映射成為標準的HTTP方法——為了消除歧義,我創(chuàng)建了一組全新的資源。“這是騙人的把戲”,我聽見你叫嚷著。 不,這不是欺騙。標識一個顧客的URI上的GET方法正好相當于getCustomerDetails操作。有人用三角形形象化地說明了這一點:

    Knobs one can turn

    把三個頂點想象為你可以調節(jié)的按鈕。可以看到在第一種方法中,你擁有許多操作,許多種類的數據以及固定數量的“實例”(本質上和你擁有的服務程序數 量一致)。在第二種方法中,你擁有固定數量的操作,許多種類的數據和許多調用固定方法的對象。它的意義在于,證明了通過這兩種方式,你基本上可以表示任何 你喜歡的事情。

    為什么使用標準方法如此重要?從根本上說,它使你的應用成為Web的一部分——應用程序為Web變成Internet上最成功的應用所做的貢獻,與 它添加到Web中的資源數量成比例。采用RESTful方式,一個應用可能會向Web中添加數以百萬計的客戶URI;如果采用CORBA技術并維持應用的 原有設計方式,那它的貢獻大抵只是一個“端點(endpoint)”——就好比一個非常小的門,僅僅允許有鑰匙的人進入其中的資源域。

    統(tǒng)一接口也使得所有理解HTTP應用協(xié)議的組件能與你的應用交互。通用客戶程序(generic client)就是從中受益的組件的例子,例如curl、wget、代理、緩存、HTTP服務器、網關還有Google、Yahoo!、MSN等等。

    總結如下:為使客戶端程序能與你的資源相互協(xié)作,資源應該正確地實現默認的應用協(xié)議(HTTP),也就是使用標準的GET、PUT、POST和DELETE方法。

    資源多重表述

    到目前為止我們一直忽略了一個稍微復雜的問題:客戶程序如何知道該怎樣處理檢索到的數據,比如作為GET或者POST請求的結果?原因是,HTTP 采取的方式是允許數據處理和操作調用之間關系分離的。換句話說,如果客戶程序知道如何處理一種特定的數據格式,那就可以與所有提供這種表述格式的資源交 互。讓我們再用一個例子來闡明這個觀點。利用HTTP內容協(xié)商(content negotiation),客戶程序可以請求一種特定格式的表述:

    GET /customers/1234 HTTP/1.1
    Host: example.com
    Accept: application/vnd.mycompany.customer+xml

    請求的結果可能是一些由公司專有的XML格式表述的客戶信息。假設客戶程序發(fā)送另外一個不同的請求,就如下面這樣:

    GET /customers/1234 HTTP/1.1
    Host: example.com
    Accept: text/x-vcard

    結果則可能是VCard格式的客戶地址。(在這里我沒有展示響應的內容,在其HTTP Content-type頭中應該包含著關于數據類型的元數據。)這說明為什么理想的情況下,資源表述應該采用標準格式——如果客戶程序對HTTP應用協(xié) 議和一組數據格式都有所“了解”,那么它就可以用一種有意義的方式與世界上任意一個RESTful HTTP應用交互。 不幸的是,我們不可能拿到所有東西的標準格式,但是,或許我們可以想到在公司或者一些合作伙伴中使用標準格式來營造一個小環(huán)境。當然以上情況不僅適用于從 服務器端到客戶端的數據,反之既然——倘若從客戶端傳來的數據符合應用協(xié)議,那么服務器端就可以使用特定的格式處理數據,而不去關心客戶端的類型。

    在實踐中,資源多重表述還有著其它重要的好處:如果你為你的資源提供HTML和XML兩種表述方式,那這些資源不僅可以被你的應用所用,還可以被任意標準Web瀏覽器所用——也就是說,你的應用信息可以被所有會使用Web的人獲取到。

    資源多重表述還有另外一種使用方式:你可以將應用的Web UI納入到Web API中——畢竟,API的設計通常是由UI可以提供的功能驅動的,而UI也是通過API執(zhí)行動作的。將這兩個任務合二為一帶來了令人驚訝的好處,這使得 使用者和調用程序都能得到更好的Web接口。

    總結:針對不同的需求提供資源多重表述。

    無狀態(tài)通信

    無狀態(tài)通信是我要講到的最后一個原則。首先,需要著重強調的是,雖然REST包含無狀態(tài)性(statelessness)的觀念,但這并不是說暴露功能的應用不能有狀態(tài)——
    事 實上,在大部分情況下這會導致整個做法沒有任何用處。REST要求狀態(tài)要么被放入資源狀態(tài)中,要么保存在客戶端上。或者換句話說,服務器端不能保持除了單 次請求之外的,任何與其通信的客戶端的通信狀態(tài)。這樣做的最直接的理由就是可伸縮性—— 如果服務器需要保持客戶端狀態(tài),那么大量的客戶端交互會嚴重影響服務器的內存可用空間(footprint)。(注意,要做到無狀態(tài)通信往往需要需要一些 重新設計——不能簡單地將一些session狀態(tài)綁縛在URI上,然后就宣稱這個應用是RESTful。)

    但除此以外,其它方面可能顯得更為重要:無狀態(tài)約束使服務器的變化對客戶端是不可見的,因為在兩次連續(xù)的請求中,客戶端并不依賴于同一臺服務器。一 個客戶端從某臺服務器上收到一份包含鏈接的文檔,當它要做一些處理時,這臺服務器宕掉了,可能是硬盤壞掉而被拿去修理,可能是軟件需要升級重啟——如果這 個客戶端訪問了從這臺服務器接收的鏈接,它不會察覺到后臺的服務器已經改變了。

    理論上的REST

    我承認:以上我所說的REST不是真正的REST,而且我可能有點過多地熱衷于簡單化。但因為我想有一個與眾不同的開場,所以沒有在一開始就介紹其正式的定義和背景。現在就讓我們稍微簡要地介紹一下這方面的內容。

    首先,先前我并沒有明確地區(qū)分HTTP、RESTful HTTP和REST。要理解這些不同方面之間的關系,我們要先來看看REST的歷史。

    Roy T. Fielding在他的博士學位論文(實際上你應該訪問這個鏈接——至少對于一篇學術論文來說,它是相當易讀的。此論文已被翻譯成中文) 中定義了術語REST。Roy曾是許多基本Web協(xié)議的主要設計者,其中包括HTTP和URIs,并且他在論文中對這些協(xié)議提出了很多想法。(這篇論文被 譽為“REST圣經”,這是恰當的——畢竟,是作者發(fā)明了這個術語,所以在定義上,他寫的任何內容都被認為是權威的。)在論文中,Roy首先定義一種方法 論來談論架構風格——高級、抽象的模式,來表達架構方法背后的核心理念。每一個架構風格由一系列的約束(constraints)定義形成。架構風格的例子包括“沒有風格”(根本沒有任何約束)、管道和過濾器(pipe and filter)、客戶端/服務器、分布式對象以及——你猜到它了——REST。

    如果對你來說這些聽起來都太抽象了,那就對了——REST在本質上是一個可以被許多不同技術實現的高層次的風格,而且可以被實例化——通過為它的抽 象特性賦上不同的值。比如,REST中包含資源和統(tǒng)一接口的概念——也就是說,所有資源都應該對這些相同的方法作出反應。但是REST并沒有說明是哪些方 法,或者有多少方法。

    REST風格的一個“化身”便是HTTP(以及一套相關的一套標準,比如URI),或者稍微抽象一些:Web架構自身。接著上面的例子,HTTP使 用HTTP動詞作為REST統(tǒng)一接口的“實例”。由于Fielding是在Web已經(或者至少是大部分)“完善”了之后才定義的REST風格,有人可能 會爭論兩者是不是100%的匹配。但是無論如何,整體上來說Web、HTTP和URI僅僅是REST風格的一個主要實現。不過,由于Roy Fielding即是REST論文的作者,又對Web架構設計有過深遠的影響,兩者相似也在情理之中。

    最后,我在前面一次又一次地使用著術語“RESTful HTTP”,原因很簡單:許多使用HTTP的應用因為一些理由并沒有遵循REST原則,有人會說使用HTTP而不遵循REST原則就等同于濫用HTTP。 當然這聽起來有點狂熱——事實上違反REST約束的原因通常是,僅僅因為每個約束帶來的設計權衡可能不適合于一些特殊情況。但通常,違背REST約束的原 因可歸咎于對其好處認知的缺乏。來看一個明顯的反面案例:使用HTTP GET調用類似于刪除對象的操作,這違反了REST的安全約束和一般性常識(客戶程序不應為此負責,服務器端開發(fā)人員大概不是有意而為之)。但在隨后的文 章中,我會提及更多這樣或那樣的對HTTP的濫用。

    總結

    本文試圖對REST(Web架構)背后的概念提供快速的介紹。RESTful HTTP暴露功能的方式與RPC、分布式對象以及Web Services是不相同的;要真正理解這些不同是需要一些心態(tài)的轉變。不管你構建的應用是僅僅想暴露Web UI還是想把API變成Web的一份子,了解下REST的原則還是有好處的。

    Stefan Tilkov是InfoQ SOA社區(qū)的首席編輯,并且是位于德國和瑞士的innoQ公司的共同創(chuàng)始人、首席顧問和REST狂熱分子首領。


    posted on 2008-06-30 10:29 gembin 閱讀(672) 評論(0)  編輯  收藏 所屬分類: SOA

    導航

    統(tǒng)計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: 亚洲男人的天堂一区二区| 亚洲视频一区在线| 18gay台湾男同亚洲男同| 亚洲成av人在线视| 久久亚洲sm情趣捆绑调教| 亚洲a∨国产av综合av下载 | 国产特级淫片免费看| 久久久久亚洲AV成人无码网站| 亚洲中文字幕无码中文字| 巨胸喷奶水www永久免费| 操美女视频免费网站| 亚洲国产精品久久久久| 国产精品久久亚洲一区二区 | 亚洲成a∨人片在无码2023| 国产一区二区三区免费| 全部免费毛片在线| 亚洲国产综合在线| 免费看黄的成人APP| 亚洲国产午夜中文字幕精品黄网站| 久久亚洲精品无码VA大香大香| 永久免费不卡在线观看黄网站| 成年女人永久免费观看片| 久久久无码精品亚洲日韩按摩| 一区二区三区在线免费观看视频| 免费a级毛片大学生免费观看| 亚洲天堂福利视频| 亚洲性线免费观看视频成熟| 亚洲美女视频免费| 色哟哟国产精品免费观看| 亚洲国产精品张柏芝在线观看| 亚洲人成未满十八禁网站| 国产精品嫩草影院免费| 久久WWW免费人成—看片| 国产91在线|亚洲| 亚洲精品自产拍在线观看| 免费无码H肉动漫在线观看麻豆| 亚洲一区精品中文字幕| 毛片免费观看的视频| 久久亚洲AV成人无码国产电影| 亚洲精品国产日韩无码AV永久免费网 | 亚洲男女一区二区三区|