分享 理解本质的 REST

vito · October 09, 2017 · Last by wuguzaliang replied at February 07, 2018 · 12146 hits
Topic has been selected as the excellent topic by the admin.

REST 本身是一个高度抽象化的架构风格,因而总是很难对它有一个比较深入且印象深刻的理解。写这篇文章的目的,是自己对学习 REST 的一个总结,也希望可以通过这篇文章,能够让读者真正的理解 REST。

本文主要内容

  • 什么是 REST
    • REST 概念
    • REST 的由来
    • REST 的理解
  • REST 的架构约束条件
    • 客户/服务器模型
    • 无状态
    • 缓存
    • 统一接口
    • 分层系统
    • 小结
  • 总结

什么是 REST

REST 的概念

先来看看百度对 REST 的定义:

REST 即表述性状态传递(英文:Representational State Transfer,简称 REST)是 Roy Fielding 博士在 2000 年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。

  • 我们更多的将 REST 称为表述性状态转移
  • 所谓的表述性状态转移,是对什么的表述?——资源
  • REST 省略了主语 Resource(资源),全称是 Resource Representational State Transfer,即资源表述性状态转移。通俗来讲就是:资源在网络中以某种表现形式进行状态转移。
  • 如果一个架构符合 REST 原则,就称它为 RESTful 架构。

在对 REST 更深一步的解释之前,我们先来看看 REST 的由来,而这对于 REST 的理解至关重要。

REST 的由来

首先简单了解一下作者——Roy Thomas Fielding

  • HTTP/1.0协议专家组成员
  • HTTP/1.1协议专家组负责人
  • Apache HTTP 服务器的核心开发者
  • Apache 软件基金会合作创始人

Roy Thomas Fielding

一张图说明 REST 的由来:

REST的由来

好吧,这是一张很简陋的图,不过用来解释 REST 的由来足够了。 故事得从远古时期的 HTTP/1.0 协议说起,随着 web 技术的发展,沿用多年且面向静态文档的 HTTP/1.0 协议无法满足 web 应用的开发需求,作为 HTTP/1.0 协议专家组成员之一的 Roy Fielding 脱颖而出,成为了 HTTP/1.1 协议专家组的负责人,负责统筹制定新版本的协议。 Roy Fielding 和他的同事们在制定 HTTP/1.1 协议的过程中,从技术架构层面对 web 之所以能获得巨大成功做了一番深入的研究和总结,之后将这些总结纳入到一套理论框架之中,并利用这套理论框架中的指导原则,指导 HTTP/1.1 协议的设计方向。经过三年的修订,HTTP/1.1 协议于 1999 年 6 月正式成为规范。HTTP/1.1 协议设计取得了极大的成功,在发布之后的十年里,都没有多少人认为有修订的必要。 Fielding 在完成 HTTP/1.1 协议的设计工作之后,回到了加州大学欧文分校继续攻读自己的博士学位。第二年(2000 年)在他的博士学位论文 Architectural Styles and the Design of Network-based Software Architectures 中(中文版名为《架构风格与基于网络的软件架构设计》),Fielding 更为系统、严谨地阐述了这套理论框架,并且使用这套理论框架推导出了一种新的架构风格,并且为这种架构风格取了一个令人轻松愉快的名字“REST”——Representational State Transfer(表述性状态转移)的缩写。 这便是 REST 的由来,可以看出,REST 架构风格,是通过推导 web 的技术架构因素层面而总结出来的,总结出来的理论框架被用来指导 HTTP/1.1 协议的设计方向。那么我们可以这样理解,REST 是 Web 自身的架构风格,REST 是 HTTP/1.1 协议等 Web 规范的设计指导原则,HTTP/1.1 协议正是为实现 REST 风格的架构而设计的。

REST 的理解

什么是 web

从 REST 的来源中我们发现,要想深刻理解 REST,首先得了解 web。 先来看一些 web 的相关知识:

百度百科 web(World Wide Web)即全球广域网,也称为万维网,它是一种基于超文本和 HTTP 的、全球性的、动态交互的、跨平台的分布式图形信息系统。是建立在 Internet 上的一种网络服务,为浏览者在 Internet 上查找和浏览信息提供了图形化的、易于访问的直观界面,其中的文档及超级链接将 Internet 上的信息节点组织成一个互为关联的网状结构。

维基百科 万维网(英语:World Wide Web),亦作“WWW”、“Web”,是一个由许多互相链接的超文本组成的系统,通过互联网访问。 万维网并不等同互联网,万维网只是互联网所能提供的服务其中之一,是靠着互联网运行的一项服务。 互联网万维网用语经常被使用且没有太多区别。然而,两者是不一样的。互联网是电脑网络互相连接的全球系统。相较之下,万维网是全球收集的文件和其他资源,通过超链接和 URIs 连接。万维网资源通常使用 HTTP 访问,这是互联网通信协议的一种。 万维网的核心部分是由三个标准构成的:

  • 统一资源标识符(URI),这是一个统一的为资源定位的系统。
  • 超文本传送协议(HTTP),它负责规定客户端和服务器怎样互相交流。
  • 超文本标记语言(HTML),作用是定义超文本文档的结构和格式。

总结来说,web 是一个由许多相互链接的超文本组成的系统,它使用 URI 来定位系统中的每一个资源,并通过 HTTP 协议进行数据的交互。 更抽象的说,Web 是一个分布式信息系统,为超文本文件和其他对象(资源)提供访问接口和访问机制。 理解了什么是 web,我们便可以更好地理解什么是 REST 了。作为 web 自身的架构风格,我们直接给出结论:REST 本质上是一种分布式超媒体系统的应用层解决方案,它为资源互通和资源管理的分离提出了一系列架构约束和原则,得到一个功能强、性能好、适宜通信的以网络为基础的应用软件架构。 这个结论依然很难理解,但我们需要对此有一个概念了解。接下来我们会对 REST 进行更为详细的介绍。

REST 词组

要理解 REST,首先需要理解(Resource)Representational State Transfer 这个词组。

资源(Resource)

REST 对于信息的核心抽象是资源。任何能被命名的信息都能作为一个资源:一份文档、一个与时间相关的服务(例如,“洛杉矶今日的天气”),一个其他资源的集合、一个非虚拟的对象(例如,人)等等。 换句话说,可以作为创作者的超文本引用的目标(the target of an author's hypertext reference)的任何概念都必须符合资源的定义。资源是到一组实体的概念性映射(a conceptual mapping),而不是在任何特定时刻与该映射相关联的实体本身。 更精确地说,资源 R 是一个随时间变化的成员函数该函数根据时间 t 将资源映射到一个实体或值的集合,集合中的值可能是资源表述(resource representations)和/或资源标识符(resource identifiers)(两者是等价的)。 对于一个资源来说,唯一必须静态的是映射的语义,因为语义才是区别资源的关键。 正是资源的这个抽象定义,使得 Web 架构的核心功能得以实现。首先,它包含了很多信息的来源,并没有人为地通过类型或实现对它们加以区分,从而实现了通用性。其次,它允许引用到表述的延迟绑定,从而支持基于请求的性质来进行内容协商。最后,它允许创作者引用一个概念而不是引用此概念的某个单独的表述,从而使得当表述改变时无需修改所有的现有链接(假设创作者使用了正确地标识符)

如何来理解“对于一个资源来说,唯一必须静态的是映射的语义,因为语义才是区别资源的关键”这句话呢?举一个简单的例子来说明一下: “一个 APP 的当前版本”是一个资源,而“一个 APP 的最稳定版本”也是一个资源,尽管这两个资源在某个时刻上可能会映射到相同的值,但它们是是截然不同的,且两个资源能够被单独地标识和引用。

资源标识符

REST 使用资源标识符来表示组件之间交互所涉及的特定资源。REST 连接器提供了访问和操作资源的值集合的一个通用的接口,而无须关心其成员函数(membership function)是如何定义的,或者处理请求的软件是何种类型。由命名权威(naming authority)来为资源分配资源标识符,使得引用资源成为可能,映射的语义有效性也由同样的命名权威来负责维护(例如,确保成员函数不会改变)。 传统的超文本系统通常只在一个封闭的或局部的环境中运行,它们使用随信息的变化而改变的唯一节点或文档标识符,并依赖链接服务器(link server)以独立于内容的方式来维护引用。因为集中式的链接服务器完全无法满足 Web 的超大规模和跨越多个组织领域的需求,所以 REST 采用了其他的方式——以来资源的创作者来选择最符合被标识的概念本质的资源标识符。

资源标识符为访问和操作资源的值集合提供了一个通用的接口。换句话说,我们抽象出来的资源都应该是可标识的,都应该拥有一个明显的 ID——在 Web 中,代表 ID 的统一概念是:URI(统一资源标识符)。URI 构成了一个全局命名空间,使用 URI 标识关键资源意味着这些资源获得了一个唯一、全局的 ID。 举个简单的例子:如果在一个类似于 Amazon.com 的在线商城中,没有用唯一的 ID(一个 URI)标识它的每一件商品,可想而知这将是多么可怕的业务决策。

表述(Representations)

资源的表述是一段对于资源在某个特定时刻的状态的描述。 资源在外界的具体呈现,可以有多种表述 (或称为表现、表示) 形式,在客户端和服务端之间传送的也是资源的表述,而不是资源本身。例如文本资源可以采用 html、xml、json 等格式,图片可以使用 PNG 或 JPG 展现出来。资源的表述包括数据和描述数据的元数据,例如,HTTP 头“Content-Type”就是这样一个元数据属性。 更确切的说:

REST 组件使用表述来捕获某个资源的当前状态或预期状态,随后在组件之间移交该表述,同过这种方式在资源上执行各种动作(perform actions on a resource)。表述(representation)有一个字节序列和描述这些字节的表述元数据(representation metadata)构成。表述的其他常用但不精确的名称包括:文档、文件、HTTP 消息实体、实例或变量。 表述由数据、描述数据的元数据、以及(有时候存在的)描述元数据的元数据组成(通常用来验证消息的完整性)。 表述的数据格式被称为媒体类型(media type)。

简单总结一下:

  • 资源总是以某种表述为载体显示的,即序列化的信息
  • 资源的表述是 REST 架构的表现层
  • 资源可以有多重表述

状态转移

状态转移:在客户端和服务器端之间转移(transfer)代表资源状态的表述。通过转移和操作资源的表述,来间接实现操作资源的目的。 访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。 互联网通信协议 HTTP 协议,是一个无状态协议。这意味着,所有的资源状态都保存在服务器端。因此,如果客户端想要操作服务器中的资源,必须通过某种手段,让服务器端的资源发生"状态转移"(State Transfer)。而这种转化是建立在表述之上的,所以就是"表述性状态转移"。 客户端使用的手段,在 web 中就是 HTTP 协议。具体来说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:

  • GET——获取资源
  • POST——新建资源(也可以用于更新资源)
  • PUT——更新资源
  • DELETE——删除资源

小结

Resource Representational State Transfer,资源表述性状态转移,即就是:根据数据抽象出来的资源,以某种表现形式,通过某种手段,在网络中发生状态转移,以此来间接实现操作资源的目的。表述性状态转移(REST)架构风格是对分布式超媒体系统中的架构元素的一种抽象。 在 web 中,具体而言:

  • 每一个 URI 代表一种资源;
  • 客户端和服务器之间,传递这种资源的某种表现层;
  • 客户端通过四个 HTTP 动词,对服务器端资源进行操作,实现"表现层状态转化"。

我们再来换一个角度,以搭建系统的角色来思考这个问题: 在 web 中,为了获取我们需要的分布在不同地域的超媒体资源,我们该如何设计这个系统?显然,web 中有着大量的,分布在不同地方的各种类型的资源。我们需要提供的是一个大型分布式超媒体系统的应用层解决方案。 首先我们需要为所需的数据设定唯一标识,因此我们将数据进行抽象为资源,并使用统一资源标识符(URI)为每个资源设定 ID,这样我们就有办法来操作每个资源。 那么该如何操作资源呢?换句话说,当我们看到一个 URI 并将它输入到浏览器中是,为何浏览器知道该怎样处理这个 URI?事实上,浏览器知道如何去处理 URI 的原因在于:所有的资源都支持同样的接口(URI),支持一套同样的方法(HTTP 动词)。这样,当我们自己按照这种方式来定义我们自己的资源时,web 中的其他人便可以轻松的获取这些资源。 获取资源时,我们可能需要不同的呈现方式或是需求,因此我们需要对资源进行表述,使其表现为我们需要的形式。

从分布式系统的角度来看 REST,我们发现以资源为核心的 REST 确实提供了一种解决大型分布式资源系统的解决方案,而 web 的成功也确实验证了这套理论的正确性。

REST 的架构约束条件

REST 作为一种组织 web 服务的架构风格,提出了一系列架构级约束。如果一个系统满足这些约束,那该系统就被称为是 RESTful 的。接下来,我们会逐条说明 REST 的五条必要约束。

客户/服务器模型

通信只能由客户端单方面发起,表现为请求 - 响应的形式。

客户 - 服务器约束背后的原则是分离关注点。通过分离用户界面和数据存储这两个关注点,我们改善了用户界面跨多个平台的可移植性;同时通过简化服务器组件,改善了系统的可伸缩性。然而,对于 Web 来说,最重要的是这种关注点的分离使得组件可独立地进化,从而支持多个组织领域的互联网规则的需求。

无状态

我们接下来在为客户 - 服务器交互添加一个架构约束:通信必须在本质上是无状态的,从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器端的上下文,会话状态因此要全部保存在客户端。

前面我们分析 REST 词组时,提到了资源的状态转移,而在这里,REST 约束中又包含了无状态通信原则,看起来仿佛是矛盾了:既然“无状态”,又怎么能说“状态转移”呢? 其实,这里说的无状态通信原则,并不是说客户端应用不能有状态,而是指服务端不应该保存客户端状态。

应用状态与资源状态

状态应该区分应用状态和资源状态,客户端负责维护应用状态,而服务端维护资源状态。客户端与服务端的交互必须是无状态的,并在每一次请求中包含处理该请求所需的一切信息。服务端不需要在请求间保留应用状态,只有在接受到实际请求的时候,服务端才会关注应用状态。 这种无状态通信原则,使得服务端和中介能够理解独立的请求和响应。在多次请求中,同一客户端也不再需要依赖于同一服务器,方便实现高可扩展和高可用性的服务端。

优点

  • 可见性——监视系统不必为了确定一个请求的全部性质去查看该请求之外的多个请求
  • 可靠性——减轻了从局部故障中恢复的任务量
  • 可伸缩性——不必在多个请求之间保存状态,从而允许服务器组件迅速释放资源,并进一步简化其实现,因为服务器不必跨多个请求管理资源的使用情况

缺点

由于不能将状态数据保存在服务器的共享上下文中,因此增加了一系列请求中发送的重复数据(每次交互的开销),可能会降低网络性能。此外,将应用状态放在客户端还降低了服务器对于一致的应用行为的控制能力,因为这样一来,应用就得依赖多个客户端版本的语义的正确实现。

缓存

为了改善网络的效率,我们添加了缓存这个架构约束。缓存架构要求一个请求的响应中的数据被隐式地或显式地标记为可缓存的或不可缓存的。如果响应是缓存的,那么客户端缓存就可以为以后的相同请求重用这个响应的数据。

优点

添加缓存可能部分或全部消除一些交互,从而通过减少一系列交互的平均延迟时间,来提高效率、可伸缩性和用户感知的性能。

缺点

如果缓存中陈旧的数据与将请求直接发送到服务器得到的数据差别极大,那么缓存会降低可靠性。

统一接口

使 REST 架构风格区别于其他基于网络的架构风格的核心特征是,它强调组件之间要有一个统一的接口。通过在组件接口上应用通用性的软件工程原则,简化了正特的系统架构,也改善了交互的可见性。实现与它们所提供的服务是解耦的的,这促进了独立地可进化性。 然而,需要的付出的代价是,统一接口降低了效率,因为信息都使用标准化的形式来移交,而不能使用特定于应用的需求的形式。REST 接口被设计为可以高效地移交大粒度的超媒体数据,并针对 Web 的常见情况做了优化,但是这也导致该接口对于其他形式的架构交互而言不是最优的。

为了获得统一的接口,需要有多个架构约束来指导组件的行为。REST 由四个接口架构约束来定义:

  • 资源的识别(identification of resources)
  • 通过表述来操作资源(manipulation of resources through representations)
  • 自描述的信息(self-descriptive messages)
  • 超媒体作为应用状态引擎(hypermedia as the engine of application state,简称 HATEOAS)

资源的识别

每个资源都拥有一个资源标识。每个资源的资源标识可以用来唯一地标明该资源。

通过表述来操作资源

这里说的是资源的自描述性。一个 REST 系统所返回的资源需要能够描述自身,并提供足够的用于操作该资源的信息,比如如何对资源进行添加,删除以及修改等操作。也就是说,一个典型的 REST 服务不需要额外的文档对如何操作资源进行说明。

自描述的信息

消息的自描述性。在 REST 系统中所传递的消息需要能够提供自身如何被处理的足够信息。例如该消息所使用的 MIME 类型,是否可以被缓存等。

超媒体作为应用状态引擎

即客户只可以通过服务端所返回各结果中所包含的信息来得到下一步操作所需要的信息,如到底是向哪个 URL 发送请求等。也就是说,一个典型的 REST 服务不需要额外的文档标示通过哪些 URL 访问特定类型的资源,而是通过服务端返回的响应来标示到底能在该资源上执行什么样的操作。一个 REST 服务的客户端也不需要知道任何有关哪里有什么样的资源这种信息。

这个描述的核心是超媒体概念,换句话说:是链接的思想。链接是我们在 HTML 中常见的概念,但是它的用处绝不局限于此(用于人们网络浏览)。考虑一下下面这个虚构的 XML 片段:

<order self="http://example.com/customers/1234"> 
   <amount>23</amount> 
   <product ref="http://example.com/products/4554"> 
   <customer ref="http://example.com/customers/1234"> 
</customer> </product></order>

如果你观察文档中 product 和 customer 的链接,就可以很容易地想象到,应用程序(已经检索过文档)如何“跟随”链接检索更多的信息。当然,如果使用一个遵守专用命名规范的简单“id”属性作为链接,也是可行的——但是仅限于应用环境之内。使用 URI 表示链接的优雅之处在于,链接可以指向由不同应用、不同服务器甚至位于另一个大陆上的不同公司提供的资源——因为 URI 命名规范是全球标准,构成 Web 的所有资源都可以互联互通。 超媒体原则还有一个更重要的方面——应用“状态”。简而言之,实际上服务器端(如果你愿意,也可以叫服务提供者)为客户端(服务消费者)提供一组链接,使客户端能通过链接将应用从一个状态改变为另一个状态。目前,只需要记住:链接是构成动态应用的非常有效的方式。 对此原则总结如下:任何可能的情况下,使用链接指引可以被标识的事物(资源)。也正是超链接造就了现在的 Web。

分层系统

为了进一步改善与互联网规模这个需求相关的行为,我们添加了分层系统架构约束。分层系统风格通过限制组件的行为(即,每个组件只能“看到”与其相交互的相邻层),将架构分解为若干层级。通过将组件对系统的知识限制在单一层级内,为整个系统的复杂性设置了边界,并且提高了底层独立性。我们能够使用层级来封装遗留服务,使新的服务免受遗留客户端的影响,做法是将不常用功能转移到一个共享中间组件中,从而简化组件的实现。中间组件还能够通过支持跨多个网络和处理器的负载均衡,来改善系统的可伸缩性。

中间件: 中间件是一种独立的系统软件或服务程序,能够连接两个独立软件或系统。分布式应用软件借助于中间件能够在不同的技术之间共享资源。即:中间件使得若干个相互独立的系统,在各自都拥有着不同的接口的情况下,仍然能通过中间件来实现通信。执行中间件的一个关键途径是信息的传递。通过中间件,应用程序可以工作在多个平台及 OS 环境中。简而言之,中间件即桥梁。

分层系统的主要缺点:增加了数据处理的开销和延迟,因此降低了用户感知的性能。对于一个支持缓存架构约束的基于网络的系统来说,可以通过在中间层使用共享缓存所获得的好处来弥补这一缺点。

小结

REST 架构风格由一组经过选择的架构约束组成,通过这些架构约束在候选架构上产生所期待的架构属性。尽管能够独立考虑其中每一个架构约束,但是根据它们在公共架构风格(common architectural styles)中的来源来对它们进行描述,使得我们理解选择它们背后的基础理论更加容易。

总结

本文试图从本质上来理解什么是 REST。 我们首先从 REST 的起源说起,发现 REST 与 Web 之间的本质关系,并从 Web 的特性,得到 REST 本质上是一个分布式超媒体系统的应用层解决方案这一结论。接着我们对 REST,即(Resource)Representational State Transfer(资源表述性状态转移)这个词组进行了详细分析,进一步得到了 REST 以资源为核心的架构风格。最后,我们对 REST 架构的五条必要约束条件进行进一步的阐述和说明,以便读者能够更为深刻地理解 REST。 这篇文章到这里就算是结束了,笔者在写下这些内容的时候依然时时感到自己知识的匮乏,以致无法更为深刻地理解 REST。笔者的这篇博客,既是希望能对自己所学做一个总结,也希望能给其他初学者带来一点帮助。文中若有理解不当的地方,欢迎批评指点。

参考资料

欢迎各位大佬批评指导

lgn21st mark as excellent topic. 09 Oct 23:30
Reply to vito

总结的非常用心,赞一记。

在写了很多年 RESTful 风格的 API 服务之后,我似乎早已忘记他的中文 资源表述性状态转移,而更多的关注我给别人用的服务是不是 RESTful 的,别人给我用的服务是不是 RESTful 的,如果是的话,就尽量利用这个统一“风格”来降低彼此使用过程中的心智负担。

简书 vito1994 兄弟?

TL;DR

反正读到一半就觉得我已经不知道 REST 为何物了 😂

支持不错

Reply to lgn21st

谢大佬认可

Reply to gingerhot

可能是自己描述的不清楚吧,REST 本身很抽象,我是对应着具体的 web 特性来学习的

👍

小意见:看到“我们会逐条说明 REST 的五条必要约束”的时候,预期接下来会有 1,2,3,4,5,但是后面只能勉强靠字号区别层级,看得不是很清楚。

学习了,楼主辛苦!

![](https://l.ruby-china.o


g/photo/2017/950e4f9e-8979-4f65-9310-9ac757bd579f.jpg!large)

两个独立的 rails5 项目,没有关联,但是知道另外一个项目的 REST 路由,如何用通过 REST 获取另外一个项目的内容(任何内容格式都可以)

两个独立的 rails 项目,一个获取另一个项目的数据时,应该是会出现跨域问题(同一局域网内端口不同也会引起跨域),我之前写了一篇文章关于 rails 跨域的,你看一下有没有帮助:http://www.jianshu.com/p/c54a1dbaab24

整个互联网上对于 REST 的迷惑,最终就落到了这个“超媒体作为应用状态引擎”(HATEOAS:Hypermedia As The Engine Of Application State)上,其他几条都没有问题。而按照 REST 原意,没有这一条就不能叫做 REST,因为它是“约束"。

在尝试了好几个项目,以及看了很多资料之后,我还是非常困惑如何在 API 方面做到这一点。这一点似乎是专门为面向人类的 HTML 阅读器:浏览器而设计的:因为如果你把链接(超媒体的要素)放在文档里让客户端使用,那么前提是客户端知道如何去使用这个”链接“。而“客户端”并不是一个人而是一个程序,它如果知道如何去使用这个链接,那么这个链接对客户端来说就是已知的了:我写过这个链接的代码,测试过它。超媒体给我的唯一信息,是我在此时可以或者不可以去使用这个链接。

举例说如果我有

<!-- GET /posts/1 -->

<post>
    <title>一个大新闻</title>
    <content>...</content>
    <link rel="like" href="/posts/1/like" /> <!-- 为这个帖子点赞的链接 -->
</post>

试想开发一个客户端的的时候,如果我看到这个链接,那么我的客户端需要能完全理解这个链接的含义:为这个帖子点赞,于是我必须事先写好,能像用户说明这个功能的 UI,比如一个点赞按钮,并且我需要用适当的手段向我的用户说明这个按钮的意义,而这一切都必须是事先准备好的。这样来说,如果 API 更新,加入了一种新的动作,例如关注,那么在我客户端不更新的前提下,我是不可能支持这种新的动作的。

然而作为浏览器,它的使用者直接是人,情况就大不一样。因为负责说明这个新动作关注的任务,就已经包含在这个返回的文档里,人类看到这个文档(浏览器的渲染)后,就已经能理解这个新动作了。

这样一来,虽然说我在编写客户端的时候,没有事先写死一个链接模板比如/post/:id/like,但是我对这种类型的链接,必须是实现有所准备的,因此虽然我可以处理超媒体,但是我能理解的超媒体控件数量,取决于我客户端软件的版本。这样一来,我认为超媒体最重要的一个意义就失败了,就是允许客户端使用超媒体去发现 API 新的能力。

如果是这样的话,那么我就无法理解为什么这一条是 REST 的一个必备条件。理论上,在上面例子当中,点赞这个动作,我可以依赖服务器在运行时给我返回一个动态的链接,但是这对客户端来说,仅仅是链接的地址有无事先约定,而链接的处理方式则是必须事先约定好的。实际使用的时候,这个链接地址动态变化所产生的不同是微乎其微的。

楼主辛苦!

You need to Sign in before reply, if you don't have an account, please Sign up first.