乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      InfoQ: 描述RESTful應(yīng)用程序

       ivy1107 2009-02-07
      Roy Fielding最近這樣說道

      要抓住這類陳述的要領(lǐng)不是件簡單的事。如果服務(wù)器不將它自己的名字空間控制在一個固定的資源層次下,客戶端及更重要的客戶端開發(fā)者將如何知道或發(fā)現(xiàn)資源的URI呢?畢竟,長久以來,分布式客戶端/服務(wù)器開發(fā)的一個基本假設(shè)就是:為了構(gòu)建、維護和管理這類應(yīng)用, 我們需要預(yù)先對應(yīng)用的接口正式描述。Roy Fielding的觀點似乎跟這個假設(shè)相沖突。

      關(guān)于描述RESTful系統(tǒng)的討論并非新鮮事物。這類討論幾乎總會得出類似上述的觀點。例如,看看前年infoQ上關(guān)于爭論:REST需要描述語言么?的備忘錄,它總結(jié)了當時發(fā)生的部分討論。今天的事態(tài)并沒有什么特別的不同。

      針對RESTful應(yīng)用的正式描述語言,雖然有大量的贊成和反對意見,但像WADL這樣的描述語言只得到了有限的發(fā)展。然而,由于缺乏一種機器能夠解釋的“標準”語言,服務(wù)器應(yīng)用所采取的最常用方法就是記錄所有URI、支持的HTTP方法和表示(representation)的結(jié)構(gòu)(如,對應(yīng)的XML和JSON格式),這樣客戶端應(yīng)用開發(fā)者就能依賴這種文檔來編寫代碼。

      但是,這種方式跟REST的一些基本原則(如Roy Fielding在上面所說的)有沖突。即便我們無視這一異議,對于那些試圖通過HTTP RESTful構(gòu)建分布式應(yīng)用的人來說,基本問題仍然存在。不正式地定義契約,服務(wù)器怎么可能得以脫身?沒有契約,我們?nèi)绾文艽_定正確實現(xiàn)了客戶端和服務(wù)器——不僅正確實現(xiàn)了各自的設(shè)計規(guī)范,而且恰當?shù)貙崿F(xiàn)了其他業(yè)務(wù)/技術(shù)策略?

      用HTTP作為應(yīng)用協(xié)議、以RESTful方式構(gòu)建的分布式應(yīng)用其實有一個契約,但其性質(zhì)和種類卻不相同。我們需要知道尋找的目標和位置。如果我們打算提出一種描述語言,那么它就要和Roy Fielding所說的保持一致,它不能是類似WSDL或WADL這樣的東西。在這篇文章中,我的目標是回答如下問題:

      • 為什么還沒有一個針對RESTful應(yīng)用的標準描述語言?
      • RESTful應(yīng)用的契約應(yīng)該是個什么樣子?
      • 我們需要構(gòu)建哪種軟件,它才能理解和利用這樣的契約?
      • 如果我們決定提出機器可讀的描述,它會是什么樣子?

      請讓我從一個示例開始。

      示例

      任務(wù)是寫一個客戶端程序,實現(xiàn)同一位客戶在不同銀行賬戶間的轉(zhuǎn)賬業(yè)務(wù)。

      首先讓我描述一下客戶端和服務(wù)器之間的所有交互,接著看看這個契約的可能描述。

      步驟 0:用戶登錄客戶端。為了保持此次討論的重點,請讓我忽視所有安全方面的內(nèi)容。

      步驟 1:客戶端使用URI:http:///accounts?findby=7t676323a通過用戶ID查找兩個賬戶。這里的7t676323a是向銀行注冊了多個賬戶的某用戶的ID。在響應(yīng)中,服務(wù)器返回兩個賬戶ID,即AZA12093ADK31242,各自的用戶ID和當前余額如下:

      200 OK
      Content-Type: application/xml;charset=UTF-8
      <accounts xmlns="urn:org:bank:accounts">
      <account>
      <id>AZA12093</id>
      <customer-id>7t676323a</customer-id>
      <balance currency="USD">993.95</balance>
      </account>
      <account>
      <id>ADK31242</id>
      <customer-id>7t676323a</customer-id>
      <balance currency="USD">534.62</balance>
      </account>
      </accounts>
      

      我們假設(shè)跟名字空間urn:org:bank:accounts綁定的XML模式描述了示例中用到的XML文檔。

      步驟 2:由于客戶端知道兩個賬戶的ID,在必要情況下,它可以向以下URI提交GET請求以獲取每個賬戶的詳細信息:

      http:///account/AZA12093
      http:///account/ADK31242
      

      就這個示例而言,鑒于客戶端已經(jīng)擁有發(fā)起賬戶轉(zhuǎn)賬所需的信息,那么就讓我忽略這些請求。

      步驟 3:接著,客戶端通過提交如下POST請求發(fā)起賬戶轉(zhuǎn)賬:

      POST /transfers
      Host: 
      Content-Type: application/xml;charset=UTF-8
      <transfer xmlns="urn:org:bank:accounts">
      <from>account:AZA12093</from>
      <to>account:ADK31242</to>
      <amount currency="USD">100</amount>
      <note>RESTing</note>
      </transfer>
      

      服務(wù)器獲得賬戶的路由代碼(譯注:由美國銀行家協(xié)會在美聯(lián)儲監(jiān)管和協(xié)助下提出的金融機構(gòu)識別碼,很多金融機構(gòu)都有一個,主要用于銀行相關(guān)的交易,轉(zhuǎn)賬,清算等的路由確認,由9位[8位內(nèi)容+1位驗證碼]組成,主要用于美國及北美地區(qū)。),把轉(zhuǎn)賬提交給執(zhí)行轉(zhuǎn)帳的后端系統(tǒng),并返回如下內(nèi)容:

      201 Created
      Content-Type: application/xml;charset=UTF-8
      <transfer xmlns="urn:org:bank:accounts">
      <from>account:AZA12093</from>
      <to>account:ADK31242</to>
      <id>transfer:XTA8763</id>
      <amount currency="USD">100</amount>
      <note>RESTing</note>
      </transfer>
      

      轉(zhuǎn)帳并沒有結(jié)束。轉(zhuǎn)賬將在幾個工作日后異步發(fā)生(這對于銀行間交易很平常),客戶端可以使用交易ID查詢交易狀態(tài)。

      步驟 4:一天后,客戶端提交GET請求來查詢狀態(tài)。

      GET /check/XTA8763
      Host: 
      200 OK
      Content-Type: application/xml;charset=UTF-8
      <status xmlns="urn:org:bank:accounts">
      <code>01</code>
      <message xml:lang="en">Pending</message>
      </status>
      

      注意,盡管這個實現(xiàn)使用了資源、URI、表示和HTTP的統(tǒng)一接口,但它并非RESTful的。因為我們將在后續(xù)小節(jié)看到,這個示例并沒有利用REST的關(guān)鍵約束之一,即“超媒體即應(yīng)用狀態(tài)引擎”。

      在試圖使之RESTful之前,讓我先試著寫一份該示例關(guān)聯(lián)的可能用戶文檔。

      Bank.Org API - URIs

      http:///accounts?findby=someparams

      向這個URI提交GET請求可查詢銀行賬戶。它將返回一個accounts文檔。詳見XML模式。

      http:///account/{account-id}

      向這個URI提交GET請求可獲取賬戶細節(jié)。這里的{account-id}是賬戶ID。它將返回一個account文檔。詳見XML模式。

      http:///transfers

      向這個URI提交POST請求可創(chuàng)建一個賬戶轉(zhuǎn)賬。在請求體中包含了transfer文檔。如果請求成功,服務(wù)器會返回一個transfer文檔。詳見XML模式。

      http:///check/{transaction-id}

      向這個URI提交GET請求可查詢轉(zhuǎn)賬狀態(tài)。這里的{transaction-id}是賬戶轉(zhuǎn)賬的ID。它會返回一個status XML文檔。詳見XML模式。

      這種風(fēng)格的文檔在如今很普遍。它包含了客戶端將一直需要使用的所有URI。它描述了客戶端用每個URI可使用的HTTP方法。它還包含了表示的描述,即示例中的XML文檔。

      但是這類文檔有兩個問題。首先,它對任何尋找機器可讀正式描述的人并沒有任何幫助。缺少機器可讀的描述,我們就無法構(gòu)建能用于測試或以其他方式執(zhí)行契約的通用軟件工具。缺乏這類通用軟件工具,對于那些需要部署這類工具來管理和治理他們軟件的人來說,這實在是一個相當大的障礙。你可能會考慮使用WADL,或者甚至是WSDL 2.0來提供一個機器可讀的等價物。

      其次,同時也是更重要的,用這種方式描述服務(wù)器接口,不論是像WADL或者WSDL 2.0這樣機器可讀的格式,還是人類可讀的格式,都違反了REST的兩個約束。這兩個約束要求(a)消息是自描述的,(b)超媒體為應(yīng)用狀態(tài)的引擎。怎樣才能做到這些,并且為什么這樣做很重要呢?

      回到約束

      REST的關(guān)鍵約束是(a)資源標示,(b)通過表示操控資源,(c)自描述的消息,(d)超媒體即應(yīng)用狀態(tài)引擎。

      在使用HTTP的RESTful應(yīng)用中,消息利用兩種東西實現(xiàn)了自描述,其一,通過使用無狀態(tài)的統(tǒng)一接口;其二,通過使用HTTP報頭(Header),它描述了消息內(nèi)容,除此之外還包括HTTP實現(xiàn)相關(guān)的各協(xié)議方面(如內(nèi)容協(xié)商、針對緩沖的條件請求和優(yōu)化并發(fā)等等)。

      通過檢查使用的HTTP方法和請求/響應(yīng)報頭,像代理或緩存這樣的中間實體就能夠破譯哪部分協(xié)議(即HTTP)正在被使用以及它們是如何被使用的。這類自描述信息保證了客戶端和服務(wù)器之間的交互是可見的(如,對緩存的使用),可靠的(如檢測局部故障并從中恢復(fù))和可伸縮的。

      第四個約束,即“超媒體即應(yīng)用狀態(tài)引擎”,有兩個用途。第一,它不要求協(xié)議(即HTTP)是有狀態(tài)的。第二,它使服務(wù)器可以演變(如,通過引入新的URI)并保持了客戶端跟服務(wù)器間的松耦合。

      服務(wù)器要是象前一節(jié)那樣提供表示的描述,它就沒有利用HTTP自描述的特性。在HTTP中,客戶端和服務(wù)器使用“媒體類型(media type)”,或者是那些我們在請求/響應(yīng)報頭中看到的Content-Type頭信息來描述消息內(nèi)容,而不是XML模式。媒體類型類似于對象的類或者XML元素的模式類型(schema type)。

      此外,如果服務(wù)器把所有URI都向它的客戶端描述,它就無法獨立演變,而且接口會變得脆弱。URI的任何改變都有可能讓現(xiàn)有客戶端無法正常工作。但是,你怎樣才能在對客戶端需要連接的URI一無所知的情況下編寫客戶端呢?

      答案就是使用具有已知關(guān)系的鏈接。鏈接是一種間接機制,客戶端可以用它來在運行時發(fā)現(xiàn)URI。一個鏈接至少有兩個屬性——URI和關(guān)系。URI指向資源或者資源的表示,而關(guān)系則描述了鏈接的類型或種類。一個真正的RESTful服務(wù)器應(yīng)用是通過在其表示中包含預(yù)定義關(guān)系的鏈接來把 URI傳給客戶端。于是,客戶端可以無需預(yù)先了解所有URI,而是在運行時從鏈接中抽取出URI。由此,服務(wù)器可以自由地改變URI,或者甚至在相同或者其他提供兼容性行為的服務(wù)器上引入新URI。

      最后,通過告知客戶端隨后要做的事,服務(wù)器在表示中返回的鏈接可能是上下文相關(guān)的。 換句話說,鏈接以一種運行時工作流的形式動態(tài)地描述了客戶端和服務(wù)器之間的契約。

      總而言之,對于RESTful應(yīng)用來說,契約包含三個不同部分:統(tǒng)一接口、表示的媒體類型和資源的上下文相關(guān)鏈接。

      聽起來有些像童話?為了實際地展示這種契約,我會重寫上面的示例。

      重寫示例

      步驟 0:同前。

      步驟 1:客戶端使用相同的URI——http:///accounts?findby=someparams搜索賬戶。這次,讓服務(wù)器返回不同類型的響應(yīng)。

      200 OK
      Content-Type: application/vnd..account+xml;charset=UTF-8
      <accounts xmlns="urn:org:bank:accounts">
      <account>
      <id>AZA12093</id>
      <link href="http:///account/AZA12093" rel="self"/>
      <link rel="http:///rel/transfer edit"
      type="application/vnd..transfer+xml"
      href="http:///transfers"/>
      <link rel="http:///rel/customer"
      type="application/vnd..customer+xml"
      href="http:///customer/7t676323a"/>
      <balance currency="USD">993.95</balance>
      </account>
      <account>
      <id>ADK31242</id>
      <link href="http:///account/ADK31242" rel="self"/>
      <link rel="http:///rel/transfer"
      type="application/vnd..customer+xml"
      href="http:///transfers"/>
      <link rel="http:///rel/customer"
      type="application/vnd..customer+xml"
      href="http:///customer/7t676323a"/>
      <balance currency="USD">534.62</balance>
      </account>
      </accounts>
      

      在這個響應(yīng)中,請注意Content-Type報頭的值,以及包含URI的鏈接(link)。

      步驟 2:如果客戶端希望了解每個賬戶的更多內(nèi)容,它可以從上述響應(yīng)的“self”關(guān)系的鏈接中抽取出賬戶URI,向這些URI提交GET請求。

      步驟 3:為了發(fā)起賬戶轉(zhuǎn)賬,客戶端從上述兩個賬戶中任選一個,并從具備“http:///rel/transfer”和“edit”關(guān)系的鏈接中抽取出URI,向之提交一個POST請求。

      POST /transfers
      Host: 
      Content-Type: application/vnd..transfer+xml;charset=UTF-8
      <transfer xmlns="urn:org:bank:accounts">
      <from>account:AZA12093</from>
      <to>account:ADK31242</to>
      <amount currency="USD">100</amount>
      <note>RESTing</note>
      </transfer>
      

      同樣請注意Content-Type報頭的值。

      發(fā)起賬戶轉(zhuǎn)賬之后,服務(wù)器返回如下內(nèi)容:

      201 Created
      Content-Type: application/vnd..transfer+xml;charset=UTF-8
      <transfer xmlns="urn:org:bank:accounts">
      <link rel="self"
      href="http:///transfer/XTA8763"/>
      <link rel="http:///rel/transfer/from"
      type="application/vnd..account+xml"
      href="http:///account/AZA12093"/>
      <link rel="http:///rel/transfer/to"
      type="application/vnd..account+xml"
      href="http:///account/ADK31242"/>
      <link rel="http:///rel/transfer/status"
      type="application/vnd..status+xml"
      href="http:///check/XTA8763"/>
      <id>transfer:XTA8763</id>
      <amount currency="USD">100</amount>
      <note>RESTing</note>
      </transfer>
      

      步驟 4:要想查詢賬戶轉(zhuǎn)賬的狀態(tài),客戶端可以從關(guān)系為“http:///check/XTA8763”的鏈接中抽取URI,并向它提交一個GET請求。

      這個實現(xiàn)是RESTful的,因為它使用了包含上下文相關(guān)鏈接的表示來封裝交互狀態(tài),即利用了“超媒體即應(yīng)用狀態(tài)引擎”這條約束。

      現(xiàn)在,讓我回顧并強調(diào)實現(xiàn)這種新交互集合所需的信息。首先,客戶端需要知道查詢賬戶的URI。接著,它需要知道各種鏈接關(guān)系的名字和語義。它還需要知道每個媒體類型的細節(jié)。它可以在運行時動態(tài)算出契約的剩余部分。因而,我們可以提供如下修訂后的文檔。

      Bank.Org API

      URIs

      http:///accounts?findby=someparams

      向這個URI提交GET請求可查詢銀行賬戶。你可以傳遞客戶ID或客戶名或客戶的社保號碼,將其作為findby的查詢參數(shù)值。這個資源支持application/vnd..accounts+xml媒體類型。

      鏈接類型

      self

      帶有這個關(guān)系的鏈接,其URI指向包含該鏈接的資源,如賬戶和轉(zhuǎn)賬資源。

      http:///rel/transfer and edit

      帶有這些關(guān)系的鏈接,其URI能用于創(chuàng)建新的賬戶轉(zhuǎn)賬資源。

      http:///rel/customer

      帶有這個關(guān)系的鏈接,其URI能用于獲取一個客戶資源。

      http:///rel/transfer/from

      帶有這個關(guān)系的鏈接,其URI標識轉(zhuǎn)賬的源賬戶資源。

      http:///rel/transfer/to

      帶有這個關(guān)系的鏈接,其URI標識轉(zhuǎn)賬的目標賬戶資源。

      http:///rel/transfer/status

      帶有這個關(guān)系的鏈接,其URI能用于獲取狀態(tài)資源。

      媒體類型

      application/vnd..accounts+xml

      這個媒體類型的表示包含了在urn:org:bank:accounts名字空間內(nèi)聲明的accounts文檔。詳見XML模式。

      application/vnd..transfer+xml

      這個媒體類型的表示包含了在urn:org:bank:accounts名字空間內(nèi)聲明的transfer文檔。詳見XML模式。

      application/vnd..customer+xml

      這個媒體類型的表示包含了在urn:org:bank:customer名字空間內(nèi)聲明的customer文檔。詳見XML模式。

      application/vnd..status+xml

      這個媒體類型的表示包含了在urn:org:bank:transfer名字空間內(nèi)聲明的status文檔。詳見XML模式。

      不同類型的描述

      我在上節(jié)所采用的描述RESTful應(yīng)用的方法不僅具有某些有趣的特性,亦有些古怪。

      對于那些熟悉WSDL和WADL的人來說,上節(jié)的描述可能看起來有些不合常理。我們在其中并未看到關(guān)于每個操作輸入和輸出消息的描述,而看到了媒體類型。但是,鑒于像application/xml這樣通用的媒體類型實在是太通用了,無法幫助我們區(qū)分賬戶資源的表示、客戶資源或者轉(zhuǎn)賬資源的表示。故而在這個示例中,我使用了自定義的媒體類型。每個媒體類項都以“+xml”結(jié)尾,并且按照RFC 3023進行描述,XML處理器(包括XMLHttpRequest)能夠把表示當作XML一樣進行處理。通過查看這樣的媒體類型,客戶端就知道收到的表示是一個賬戶資源,還是一個轉(zhuǎn)賬資源。更重要的是,它不必對它用來獲取那個表示的URI進行任何結(jié)構(gòu)或者語法方面的假設(shè)。

      此外,文檔并沒有列出應(yīng)用正在使用的所有的URI,而僅僅包含了賬戶轉(zhuǎn)賬客戶端需要發(fā)起交互的一個URI。注意,在不同的示例中,我們或許需要記錄 多個URI。其思想是保證預(yù)發(fā)布URI的數(shù)量最小。為什么這樣更好?原因在于,它解耦了客戶端和資源的實際URI,客戶端直到運行時才需要知道其余的 URI。

      最后,上述文檔沒有包括每個URI上可用的HTTP操作。相反,我假定客戶端會向每個URI都提交一個HTTP OPTIONS以發(fā)現(xiàn)各種可能的操作,接著使用HTTP GET獲取資源的表示,使用HTTP POST在資源集合內(nèi)創(chuàng)建一個新資源,使用HTTP PUT更新現(xiàn)有資源(或者如果客戶端可以為資源分配URI,就創(chuàng)建一個),使用HTTP DELETE刪除資源。

      總而言之,要以RESTful方式描述契約必須:

      • 預(yù)發(fā)布一些URI并記錄這些URI相應(yīng)的資源。盡量保證這個列表的長度最短。這些URI是應(yīng)用的起點。
      • 記錄所有媒體類型。對于基于XML的表示,如果需要,使用XML模式記錄每個表示的結(jié)構(gòu)。
      • 記錄所有鏈接的關(guān)系。
      • 讓客戶端在運行時使用HTTP OPTIONS去發(fā)現(xiàn)某URI支持的HTTP操作。在某些情況下,鏈接關(guān)系的類型足以讓客戶端確定服務(wù)器是否支持某個操作。

      這種描述既不完整,也不是完全機器可讀的。

      說它不是完整的,是因為它僅僅包含了契約的靜態(tài)部分,讓服務(wù)器在運行時通過鏈接描述可能的工作流。

      對于那些已經(jīng)對REST好處深信不疑并且使用HTTP積極構(gòu)建RESTful應(yīng)用的人來說,缺乏完整的機器可讀描述可能無關(guān)緊要。

      但是對于那些正在使用類RPC方法(使用SOAP、WSDL和WS-*)構(gòu)建分布式應(yīng)用以及正在考慮REST的人來說,缺乏完整機器可讀的描述可能就是個障礙了。然而,使用RESTful的機器可讀描述可做的工作量,即使存在的話,其作用也有限。這歸結(jié)于如下原因:

      • 契約的動態(tài)天性:正如我在上節(jié)示例中所描述的,表示通過在表示中使用鏈接描述了契約的動態(tài)方面。用表示之外、某些基于XML的機器可讀描述來解釋上下文相關(guān)的契約是多此一舉。
      • 媒體類型的靈活性:與基于SOAP的應(yīng)用不同,RESTful應(yīng)用不限于使用XML。它們可以使用其他沒有模式語言的媒體類型。

      同樣需要注意,為遠程接口描述一個完全機器可讀的描述契約是一種謬論。用WSDL或WADL創(chuàng)建的機器可讀描述僅能描述結(jié)構(gòu)和語法,而不能描述語義。但機器可讀的描述有時能降低我們作為程序員、測試員和管理員需要做的工作量。

      要是我們把統(tǒng)一接口和契約的動態(tài)方面擱置一邊,我們可以用機器可讀方式描述契約的剩余部分。以下就有一個示例。注意,在這個描述中,我的意圖只是想幫助那些要監(jiān)測或測試客戶端/服務(wù)器端交互的工具和框架,當然不是要模仿WSDL或WADL。

      <description xmlns:bank="urn:org:bank:accounts">
      <types>
      <!-- Include the schema used for all representations -->
      <include href="bank-schema.rng"/>
      </types>
      <!-- List all media types and the corresponding XML types -->
      <media-types>
      <media-type>
      <name>application/vnd..accounts+xml</name>
      <representation>bank:account</representation>
      </media-type>
      <media-type>
      <name>application/vnd..transfer+xml</name>
      <representation>bank:transfer</representation>
      </media-type>
      ...
      </media-types>
      <relations>
      <relation>
      <documentation>This relation ...</documentation>
      <name>http:///rel/transfer</name>
      </relation>
      ...
      </relations>
      <resources>
      <resource>
      <name>accounts</name>
      <media-type-ref>application/vnd..accounts+xml</media-type-ref>
      <uri> <!-- This is optional -->
      <base>http:///accounts</base>
      <params>
      <param>
      <documentation>Use this parameter to ...</documentation>
      <name>findBy</name>
      </param>
      </params>
      </uri>
      </resource>
      <resource>
      <name>transfer</name>
      <media-type-ref>application/vnd..transfer+xml</media-type-ref>
      </resource>
      ...
      </resources>
      </description>
      

      這是我在前節(jié)所描述的契約的機器可讀版本,很明顯,它并不符合任何標準。這個描述并沒有消除對于人類可讀描述的需要,因為我們?nèi)匀恍枰枋鰬?yīng)用語義。

      讓我強調(diào)一下這個描述中的關(guān)鍵部分:

      • 模式類型: 由于在這個示例中,我為所有的表示選擇使用XML,因而包含了所使用模式的引用。如果模式無法描述所選的表示格式,這部分將毫無意義。
      • 媒體類型以及所使用的相應(yīng)XML文檔。
      • 所有鏈接關(guān)系的列表。
      • 資源和它們媒體類型的名字。注意,這些名字不是URI。
      • 為應(yīng)用提供起始點的資源的URI。

      這種描述比人類可讀的描述更有用嗎?由于缺乏可解釋這種描述的工具和框架,答案可能是否定的。

      這種方法實用嗎?

      如果你正在編寫基于機器可讀契約(如WADL文檔)的服務(wù)器端代碼和客戶端代碼,編碼流程可能如下:

      • 從描述生成資源類。每個資源類都潛在對應(yīng)于描述中的URI。
      • 生成跟表示綁定的類。如果表示是基于XML的,我會生成跟多種XML文檔匹配的類。
      • 生成跟多種HTTP操作匹配的客戶端存根(stub)。
      • 開始編碼

      這個模型對以RESTful方式描述契約并不適用,步驟會有所不同:

      1. 讀取所有媒體類型描述。如果媒體類型是用XML模式描述的,那么就獲取這個模式,生成能夠解析或者生成XML的類。
      2. 讀取所有鏈接關(guān)系的描述。
      3. 手工創(chuàng)建資源類。
      4. 每當客戶端接收到一個表示時,除了從表示中抽取數(shù)據(jù)之外,還要查看鏈接。如果你找到一個包含已知關(guān)系的鏈接,那就抽取hreftype(如果有的話)屬性以備后用。
      5. 在客戶端,在發(fā)送HTTP請求之前,先發(fā)送一個HTTP OPTION請求檢查服務(wù)器端是否支持你要執(zhí)行的操作。如果支持,在你的客戶端應(yīng)用中激活該操作。

      我關(guān)注的大多數(shù)軟件框架都可以處理部分上述步驟(如通用接口或資源類的約定),而且還能生成創(chuàng)建或解析XML的類(這取決于你所選的編程語言)。但 是剩余部分就留給了開發(fā)者。更有甚者,這類框架多數(shù)強調(diào)服務(wù)器端編程,并在假設(shè)現(xiàn)有HTTP客戶端庫已經(jīng)足夠使用的情況下忽略了對客戶端編程的考慮。因 而,在處理上述(4)和(5)項時,可能需要創(chuàng)建自定義代碼。

      對于那些想要測試或者增強契約的軟件工具怎么辦?創(chuàng)建這種工具,讓其在運行時讀取上述機器可讀描述以完成如下工作,是可行的。

      • 檢查表示的媒體類型是否是預(yù)定義的
      • 檢查表示是否匹配媒體類型的預(yù)定義描述
      • 檢查表示中包含的所有鏈接是否有預(yù)定義關(guān)系和媒體類型,并檢查所包含URI是否符合預(yù)定義的URI模式。

      我還沒有聽說哪個軟件能以這種方式來完成以上驗證。但是,出現(xiàn)的機會很大。如果你讀到文章的這里,你就會明白那些機會是什么。

      結(jié)論

      我寫這篇文章的一個目的是要闡述這樣的事實:像WSDL和WADL這樣的傳統(tǒng)契約描述并不適合描述RESTful應(yīng)用。正如我在賬戶轉(zhuǎn)賬示例中所示 范的,只有部分契約能被靜態(tài)地描述,其余都是動態(tài)并上下文相關(guān)的。客戶端可以通過在運行時查看鏈接來遵循契約的動態(tài)部分。你可以出于設(shè)計時和測試的目的試 著用某些機器可讀文檔來描述前一部分,但是讓服務(wù)器在運行時描述其余部分會大大降低客戶端和服務(wù)器之間的耦合。試圖靜態(tài)地描述完整契約無異于會使所有上下 文相關(guān)的鏈接在表示之外重復(fù)一遍。

      相反的,諸如WSDL和WADL這樣的描述語言試圖用上下文無關(guān)的方式描述契約,并把用戶文檔留給客戶端開發(fā)者,以便他們能夠?qū)W習(xí)如何從那些描述中描述的各類消息交互模式合成客戶端應(yīng)用。在RESTful應(yīng)用中,服務(wù)器在運行時以鏈接形式提供這個信息。

      總之,RESTful是有契約的。我們只需要知道如何找到并在哪兒找到該契約,同時謹記該契約是上下文相關(guān)的,就行了。

      關(guān)于作者

      Subbu在Yahoo工作。通過他的博客可以了解關(guān)于他的更多信息。

      查看英文原文:Describing RESTful Applications。

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多