Richardson成熟度模型
Richardson Maturity Model(RMM)
邁向REST的輝煌
一個模型(由Leonard Richardson開發)將REST方法的主要元素分解為三個步驟。這些引入資源,http動詞和超媒體控件。
最近我一直在閱讀Rest In Practice的草稿:一本我的幾位同事一直在研究的書。他們的目標是解釋如何使用Restful Web服務來處理企業面臨的許多集成問題。本書的核心是網絡是大規模可擴展的分布式系統的存在證明,這種系統運行良好,我們可以從中獲得創意,更輕松地構建集成系統。
?
為了幫助解釋Web風格系統的特定屬性,作者使用由Leonard Richardson開發并?在QCon演講中解釋的寧靜成熟模型?。該模型是考慮使用這些技術的好方法,所以我認為我會對自己的解釋有所暗示。(這里的協議示例只是說明性的,我不認為值得對它們進行編碼和測試,所以細節上可能存在問題。)
0級 - XML沼澤
該模型的出發點是使用HTTP作為遠程交互的傳輸系統,但不使用Web的任何機制。基本上,你在這里做的是使用HTTP作為你自己的遠程交互機制的隧道機制,通?;谶h程過程調用。
?
假設我想與我的醫生進行預約。我的預約軟件首先需要知道我的醫生在特定日期有哪些空位,因此它會請求醫院預約系統獲取該信息。在0級情況下,醫院將在某個URI處公開服務端點。然后,我向該端點發布一份包含我的請求詳細信息的文檔。
POST /appointmentService HTTP/1.1 [various other headers]?服務器然后將返回一個文件給我這個信息
HTTP/1.1 200 OK [various headers]<openSlotList><slot start = "1400" end = "1450"><doctor id = "mjones"/></slot><slot start = "1600" end = "1650"><doctor id = "mjones"/></slot> </openSlotList>我在這里使用XML作為示例,但內容實際上可以是任何內容:JSON,YAML,鍵值對或任何自定義格式。
我的下一步是預約,我可以通過將文檔發布到端點再次完成預約。
POST /appointmentService HTTP/1.1 [various other headers]<appointmentRequest><slot doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/> </appointmentRequest>?如果一切順利,我會得到一個回復??,說我的預約已被預訂。
HTTP/1.1 200 OK [various headers]<appointment><slot doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/> </appointment>如果有問題,說別人在我之前進來,那么我會在回復正文中得到某種錯誤信息。
HTTP/1.1 200 OK [various headers]<appointmentRequestFailure><slot doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/><reason>Slot not available</reason> </appointmentRequestFailure>到目前為止,這是一個直接的RPC風格系統。這很簡單,因為它只是拋棄普通的舊XML(POX)。如果您使用SOAP或XML-RPC,它基本上是相同的機制,唯一的區別是您將XML消息封裝在某種信封中。
1級 - 資源
在RMM中實現Rest的第一步是引入資源。所以現在,我們現在開始與個人資源交談,而不是將我們的所有請求提交給單一服務端點。
因此,在我們最初的查詢中,我們可能會為給定的醫生提供資源。
POST /doctors/mjones HTTP/1.1 [various other headers]<openSlotRequest date = "2010-01-04"/>?答復包含相同的基本信息,但是現在每個插槽都是可以單獨尋址的資源。
HTTP/1.1 200 OK [various headers]<openSlotList><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/><slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/> </openSlotList>?使用特定的資源預約預約意味著發布到特定的插槽。
POST /slots/1234 HTTP/1.1 [various other headers]<appointmentRequest><patient id = "jsmith"/> </appointmentRequest>?如果一切順利,我會收到類似的回復。
HTTP/1.1 200 OK [various headers]<appointment><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/> </appointment>現在的區別是,如果任何人需要做任何有關約會的事情,比如預約一些測試,他們首先會得到預約資源,它可能有一個URI?http://royalhope.nhs.uk/slots/1234/appointment,并發布到該資源。
對于像我這樣的對象,這就像對象身份的概念。我們不是在以太網中調用某個函數并傳遞參數,而是在一個特定對象上調用一個方法,為其他信息提供參數。
2級 - HTTP動詞
我在第0級和第1級使用了HTTP POST動詞來處理所有的交互操作,但有些人使用GET或者另外使用GET。在這些級別上,它們沒有多大區別,它們都被用作隧道機制,允許您通過HTTP隧道進行交互。級別2遠離這一點,盡可能使用HTTP動詞以及它們如何用于HTTP本身。
對于我們的插槽列表,這意味著我們要使用GET。
GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 Host: royalhope.nhs.uk?答復和POST一樣
HTTP/1.1 200 OK [various headers]<openSlotList><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/><slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/> </openSlotList>在第2級,對這樣的請求使用GET至關重要。HTTP將GET定義為安全操作,即它不會對任何狀態進行任何重大更改。這使我們可以按任意順序安全地調用GET,并且每次都可以獲得相同的結果。這樣做的一個重要結果是,它允許任何參與者路由請求以使用緩存,這是使Web性能與其一樣好的關鍵因素。HTTP包含支持緩存的各種措施,可供所有通信參與者使用。通過遵循HTTP的規則,我們可以利用該功能。
預約一個約會,我們需要一個HTTP動詞,改變狀態,POST或PUT。我將使用與之前相同的POST。
POST /slots/1234 HTTP/1.1 [various other headers]<appointmentRequest><patient id = "jsmith"/> </appointmentRequest>在這里使用POST和PUT之間的權衡比我想要進入這里更多,也許我會在某一天做一個單獨的文章。但我想指出的是,有些人錯誤地在POST / PUT和創建/更新之間建立了對應關系。他們之間的選擇是相當不同的。
即使我使用與第1級相同的帖子,遠程服務如何響應還有另一個顯著差異。如果一切順利,服務會回復201的回應代碼,以表明世界上有新的資源。
HTTP/1.1 201 Created Location: slots/1234/appointment [various headers]<appointment><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/> </appointment>201響應包含一個帶有URI的位置屬性,客戶端可以使用該URI來獲取將來該資源的當前狀態。此處的響應還包括該資源的表示,以便立即保存客戶端的額外呼叫。
如果出現問題,還有其他差異,例如其他人預訂會話。
HTTP/1.1 409 Conflict [various headers]<openSlotList><slot id = "5678" doctor = "mjones" start = "1600" end = "1650"/> </openSlotList>此響應的重要部分是使用HTTP響應代碼來指示出現問題。在這種情況下,409似乎是一個很好的選擇,表明其他人已經以不兼容的方式更新資源。我們沒有使用200的返回碼,而是包含一個錯誤響應,我們明確地使用了這種類型的錯誤響應。協議設計人員需要決定使用哪些代碼,但如果出現錯誤,應該有非2xx響應。2級介紹了使用HTTP動詞和HTTP響應代碼。
這里存在不一致性。REST倡導者討論使用所有HTTP動詞。他們還通過說REST試圖從網絡的實際成功中學習來證明他們的方法是合理的。但是世界范圍的網絡在實踐中并不使用PUT或DELETE。有更明智的理由使用PUT和DELETE,但Web的存在證明不是其中之一。
網絡存在的關鍵要素是安全(如GET)和非安全操作之間的強烈分離,以及使用狀態代碼來幫助傳達您遇到的各種錯誤。
等級3 - 超媒體控制
最后的關卡介紹了你經常聽到的HATEOAS(超文本作為應用程序狀態引擎)的簡稱。它解決了如何從列表中開放空位到知道如何做預約的問題。
我們從我們在第2級發送的相同的初始GET開始
GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 Host: royalhope.nhs.uk?但是回應有一個新的元素
HTTP/1.1 200 OK [various headers]<openSlotList><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"><link rel = "/linkrels/slot/book" uri = "/slots/1234"/></slot><slot id = "5678" doctor = "mjones" start = "1600" end = "1650"><link rel = "/linkrels/slot/book" uri = "/slots/5678"/></slot> </openSlotList>每個插槽現在都有一個鏈接元素,其中包含一個URI以告訴我們如何預約約會。
超媒體控件的重點在于它告訴我們接下來可以做什么,以及我們需要操作的資源的URI。我們不需要知道在哪里發布我們的預約請求,反饋中的超媒體控件告訴我們如何去做。
POST會再次復制第2級的內容
POST /slots/1234 HTTP/1.1 [various other headers]<appointmentRequest><patient id = "jsmith"/> </appointmentRequest>并且回復包含許多超媒體控件,用于接下來要做的不同事情。
HTTP/1.1 201 Created Location: http://royalhope.nhs.uk/slots/1234/appointment [various headers]<appointment><slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/><patient id = "jsmith"/><link rel = "/linkrels/appointment/cancel"uri = "/slots/1234/appointment"/><link rel = "/linkrels/appointment/addTest"uri = "/slots/1234/appointment/tests"/><link rel = "self"uri = "/slots/1234/appointment"/><link rel = "/linkrels/appointment/changeTime"uri = "/doctors/mjones/slots?date=20100104@status=open"/><link rel = "/linkrels/appointment/updateContactInfo"uri = "/patients/jsmith/contactInfo"/><link rel = "/linkrels/help"uri = "/help/appointment"/> </appointment>超媒體控件的一個顯而易見的好處是它允許服務器在不中斷客戶端的情況下更改其URI方案。只要客戶端查找“addTest”鏈接URI,服務器團隊就可以處理除初始入口點之外的所有URI。
另一個好處是它可以幫助客戶開發人員探索協議。這些鏈接為客戶開發人員提供了接下來可能有哪些可能的提示。它沒有提供所有信息:“最新”和“取消”控件都指向相同的URI - 他們需要弄清楚其中一個是GET,另一個是DELETE。但至少它為他們提供了一個出發點,以了解更多信息以及在協議文檔中尋找類似的URI。
同樣,它允許服務器團隊通過在響應中添加新鏈接來宣傳新功能。如果客戶開發人員留意未知鏈接,這些鏈接可能成為進一步探索的觸發器。
關于如何表示超媒體控件沒有絕對的標準。我在這里所做的是使用REST in Practice團隊的當前建議,該團隊遵循ATOM(RFC 4287)。我使用一個<link>具有uri?目標URI屬性的元素和一個rel屬性來描述這種關系。一個眾所周知的關系(例如self對元素本身的引用)是裸露的,任何特定于該服務器的關系都是完全限定的URI。ATOM指出,著名鏈接的定義是鏈接關系注冊表。正如我寫的,這些僅限于ATOM所做的事情,ATOM通常被認為是3級安寧的領導者。
級別的含義
我應該強調的是,RMM是考慮REST元素的一種好方法,而不是REST本身級別的定義。Roy Fielding已經明確指出,3級RMM是REST的前提條件。和軟件中的許多術語一樣,REST有很多定義,但是由于Roy Fielding提出了這個術語,所以他的定義應該比大多數更重要。
我覺得這個RMM有用的是它提供了一個很好的循序漸進的方式來理解平靜思維背后的基本思想。因此,我認為它是幫助我們了解概念的工具,而不是某種評估機制應該使用的東西。我認為我們沒有足夠的例子可以確定寧靜的方法是整合系統的正確方式,但我認為這是一種非常有吸引力的方法,我會在大多數情況下推薦這種方法。
在與伊恩羅賓遜談這件事時,他強調說,當倫納德理查森首次提出這個模型時,他發現這種模型具有吸引力的地方在于它與普通設計技術的關系。
- 1級通過使用分治法解決了處理復雜性的問題,將大型服務端點分解為多個資源。
- 2級引入了一組標準的動詞,以便我們以相同的方式處理類似的情況,消除不必要的變化。
- 級別3引入了可發現性,提供了一種使協議更加自我記錄的方式。
其結果是一個模型,可以幫助我們思考我們想要提供的HTTP服務類型,并構建期望與之交互的人的期望。
?
?
#
轉載于:https://www.cnblogs.com/chenxygx/p/8877726.html
總結
以上是生活随笔為你收集整理的Richardson成熟度模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab画间断坐标轴,Matlab制
- 下一篇: Flume+Kafka+Spark小案例