Richardson Maturity Model(RMM)

迈向REST的辉煌

一个模型(由Leonard Richardson开发)将REST方法的主要元素分解为三个步骤。这些引入资源,http动词和超媒体控件。

最近我一直在阅读Rest In Practice的草稿:一本我的几位同事一直在研究的书。他们的目标是解释如何使用Restful Web服务来处理企业面临的许多集成问题。本书的核心是网络是大规模可扩展的分布式系统的存在证明,这种系统运行良好,我们可以从中获得创意,更轻松地构建集成系统。

为了帮助解释Web风格系统的特定属性,作者使用由Leonard Richardson开发并 在QCon演讲中解释的宁静成熟模型 。该模型是考虑使用这些技术的好方法,所以我认为我会对自己的解释有所暗示。(这里的协议示例只是说明性的,我不认为值得对它们进行编码和测试,所以细节上可能存在问题。)

0级 - XML沼泽

该模型的出发点是使用HTTP作为远程交互的传输系统,但不使用Web的任何机制。基本上,你在这里做的是使用HTTP作为你自己的远程交互机制的隧道机制,通常基于远程过程调用

假设我想与我的医生进行预约。我的预约软件首先需要知道我的医生在特定日期有哪些空位,因此它会请求医院预约系统获取该信息。在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服务类型,并构建期望与之交互的人的期望。

#

Richardson成熟度模型的更多相关文章

  1. 几句话概括理查德成熟度模型(RESTful)

    近期做的项目中准备引入RESTful风格,特地进行了一些学习,其中比较重点的有一个理查德成熟度模型(Richardson Maturity Model),模型提出了四个等级(0-3),如下图 其中只有 ...

  2. TOGAF架构能力框架之架构合同、成熟度模型和架构技能框架

    TOGAF架构能力框架之架构合同.成熟度模型和架构技能框架 5. 架构合同 架构合同是在开发团体和赞助者之间关于架构的交付物.质量以及适用目标的联合协议,并且通过有效的架构治理将会促使这些协议的成功施 ...

  3. 企业架构研究总结(40)——TOGAF架构能力框架之架构合同、成熟度模型和架构技能框架

    5. 架构合同 架构合同是在开发团体和赞助者之间关于架构的交付物.质量以及适用目标的联合协议,并且通过有效的架构治理将会促使这些协议的成功施行.通过对合同的管理施行一个治理方法,如下几点将会得到保障: ...

  4. PCMM(人力资源能力成熟度模型)V2.0中英对照版发布

    PCMM中英版终于发布 时光荏苒,从当初的回眸到如今的回头,这才发现:坚守一份承诺是多么的不易! 一年多了,这份承载殷切期待的作品--<PCMM(人力资源能力成熟度模型)V2.0 (中英文对照版 ...

  5. 你的BI应用处于什么阶段?解读Gartner BI成熟度模型

    文 | 帆软数据应用研究院 水手哥 本文出自:知乎专栏<帆软数据应用研究院>——数据干货&资讯集中地   无论国内还是国外,多数企业的BI和分析平台建设之路并不平坦:一是对自身的环 ...

  6. CMM:软件成熟度模型

    周末在家闲来无事,泡咖啡看书,正好看到了关于CMM的相关资料,分享出来,也当做学习笔记... 一.CMM简介 CMM,英文全称为Capability Maturity Model for Softwa ...

  7. 能力成熟度模型CMM

    能力成熟度模型(Capability Maturity Model,英文缩写为CMM)[1]是 一种开发模型.Carnegie Mellon大学的研究人员从美国国防部合同承包方那里收集数据并加以研究, ...

  8. SaaS成熟度模型分级:

    SaaS成熟度模型分级: 根据SaaS应用是否具有可配置性,高性能,可伸缩性的特性,SaaS成熟度模型被分成四级.每一级都比前一级增加三中特性中的一种.   可配置 高性能 可伸缩 Level1 N ...

  9. CMMI能力成熟度模型集成的过程域

    什么是CMMI CMMI全称是Capability Maturity Model Integration, 即能力成熟度模型集成,是由美国国防部(Office of the Secretary of ...

随机推荐

  1. virtualbox 安装 mac os x lion 10.7实现全屏显示!

    1. 启动Virtual Box虚拟机,在虚拟机里编辑 /Library/Preferences/SystemConfiguration/com.apple.Boot.plist,找到 <dic ...

  2. SSH 与 SSL

    关于 ssh 有人已经总结得非常好了,这里推荐大家看下 阮一峰 写的 ssh原理与应用 写得简单易懂,非常赞. 关于 ssl  这里有一篇博文写得也不错,ssl协议详解 好了,那 ssh 和 ssl ...

  3. 阅读layim代码小记,监听事件实现方法

    (function (win) { //注册事件 var chat = function () { $('#open').on('click', function () { sendMessage() ...

  4. Softmax回归(Softmax Regression, K分类问题)

    Softmax回归:K分类问题, 2分类的logistic回归的推广.其概率表示为: 对于一般训练集:                     系统参数为:      Softmax回归与Logist ...

  5. Spring mvc实现ex导入导出

    依赖架包 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</arti ...

  6. Anaconda常用命令

    conda版本: conda --version 环境信息: 激活环境后,conda info 查看环境已安装包: conda list 新建环境: conda create -n {NAME} [ ...

  7. CSS权重的比较方法

    CSS的权重如下: !important  Infinity正无穷 行间样式  1000 id     100 class|属性|唯类 10 标签|伪元素  1 通配符   0 256进制 当出现多个 ...

  8. springBoot+mybatisPlus小demo

    项目介绍:采用restful api进行接口规范 / 项目框架SpringBoot+mybatis Plus / 采用mysql进行数据存储 / 采用swaggerUI进行前后端业务分离式开发. 开发 ...

  9. 工具 | Axure基础操作 No.2

    不废话了,直接如之前一样上操作图才是正道. 1.设置文本类型为密码或者文件类型 可以在属性中也选择最大长度制定长度. 如果设置类型为文件,在浏览器中就会自动变成选择本地文件的按钮. 2.文本框提示文字 ...

  10. 常见web漏洞

    常见的web漏洞——文件上传漏洞 一.文件上传漏洞概述    文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力.这种攻击方式是最为直接和有效的,有时候几乎没 ...