文章目录

  • REST详解
    • 词组解释
    • 论文摘要
    • REST架构约束
      • 一、Client–server:客户端-服务器
      • 二、Stateless:无状态
      • 三、Cacheability:缓存
      • 四、⭐Uniform Interface:统一接口 (==RESTful API==)
      • 五、Layered System:分层系统
      • 六、Code-On-Demand:按需代码 (可选)
    • 什么是RESTful?
  • Roy Thomas Fielding 博士 (作者简介)
  • REST与Web、HTTP、URI
  • RESTful API 设计
    • Richardson Maturity Model
    • 将版本号用于RESTful API
  • ⭐把书读薄 — 要点总结

主要参考资料 :

  • Filding博士的REST论文(本文中所提到的“论文”一词,若无特殊说明均代指此论文
    • Architectural Styles and the Design of Network-based Software Architectures 原文
    • Fielding博士的REST论文中文版 (中文版旧版-李琨主译)
    • ==架构风格与基于网络应用软件的架构设计(中文修订版)==(中文版-李琨2013年修订)
  • REST深入剖析及实践策略研究(赵峰-2009年河北大学工学硕士学位论文)
  • wiki-REST、中文wiki-REST
  • 知乎-怎样用通俗的语言解释REST,以及RESTful?

REST详解

REST,是Roy Thomas Fielding博士于2000年在他的博士论文《Architectural Styles and the Design of Network-based Software Architectures》(架构风格与基于网络应用软件的架构设计)第5章提出的一种 为分布式超媒体系统设计的REST架构风格
(这篇论文以下简称”论文”)

摘自论文

分布式:信息服务的提供商必须能够有能力满足无法控制的可伸缩性和软件组件的独立部署两方面的要求(上图述)。这促使他们采取分布式架构。REST共有6条架构约束,其中”无状态”约束最能体现出为分布式设计。
超媒体:超媒体就是通过超链接(URI)组合的多媒体信息(包括文本、图像、视频等)。人们日常使用的万维网(World Wide Web,简称web)是规模最大的超媒体系统,所有的web应用(如爱奇艺、网易云、百度、网盘等)也都是超媒体系统。

之所以Fielding专门说”超媒体系统”而非”web系统”,是因为架构师们知道设计一个东西时应当具有抽象思维,这会让它们适用性更强,而不仅仅局限于某一个应用系统。但因为web始终是规模最大的超媒体系统,所以为了不让我们的思维绕弯子,可以统一认为REST是为web设计的。并且论文也包含了很多与web相关的内容,更是在第6章专门讲述如何将REST应用于Web

Fielding博士是HTTP协议(1.0版和1.1版)和URI等Web架构标准的主要设计者、也是Apache HTTP服务器的主要设计者、Apache基金会的第一任主席,他的这篇论文是Web发展史上的一个重要的技术文献。


词组解释

REST全称Representational State Transfer
(其它资料中有各种翻译,如 表现层状态传输、表现层状态转化 等)
论文译者李琨 将其翻译为”表述性状态移交”。对于这个翻译的理解,我与李琨老师专门进行了交流,最终认为理解为”状态表述的移交“或许更好。英文与中文的语序本就有不同,那些按照顺序翻译的释义并不能很好地表达出REST的意思

论文在讲到”表述”时,其实已经用白话解释了REST

最终结合起来,REST的正确释义应该是:(资源)状态表述的移交,资源是省略的主语。
该释义可以用括号分隔成 ((资源的状态)的表述)的移交,方便更好地理解

可能会有人问:HTTP(Hyper Text Transfer Protocol)不是超文本传输协议吗,把REST的T翻译为传输不更好理解吗
实则不然。论文中提到 HTTP翻译为超文本”传输”协议是错误的,它应当是超文本”移交”协议。
REST对HTTP的开发起到了指导作用,所以HTTP的T也应该是移交的意思
详情见:HTTP 超文本移交协议

现在慢慢解释
①Resources 资源
REST的名称中,省略了主语资源是REST对于信息的核心抽象

所谓”资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它。每个资源对应一个特定的URI,要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。
所谓”上网”,就是与互联网上一系列的”资源”互动,调用它的URI。

②State 状态
资源的状态,即资源的信息,包括资源的属性和内容。比如这个资源存不存在、是什么时候创建的、内容是什么,这都属于资源的状态

③Representations 表述
representation翻译为”表述”非常之信达雅,比常用的表象、表现都更好。

REST的R是representational,是representation的形容词形式,李琨把它翻译为”表述性”,其实这个翻译让人感觉有些别扭,不那么好理解。我认为它更多的是为了迁就representation的翻译,即”表述”为名词,则”表述性”为它的形容词
所以不必过于纠结”表述性”这个翻译,重点其实在于它的名词representation

论文也专门对representations进行了解释

“使用表述来捕获某个资源的状态”,理解为 表述是资源状态的一种具象表现形式
表述由一个字节序列(二进制流,所有的信息都以二进制流进行传输)和描述这些字节的表述元数据构成,它是资源状态的具象化信息

(我认为) 基于rest风格的http的数据包的主要内容就是表述。例如

  • 请求获取某个资源内容,响应体表述了资源当前的状态
  • 请求修改某个资源内容,与此相关的 URL、请求方法(POST)、请求体(表示了修改的内容) 表述了资源要被修改的状态
  • 请求删除某个资源内容,与此相关的 URL、请求方法(DELETE) 表述了资源要被删除的状态

这些http包含的信息不是真正的资源,而是表述了资源的某一时刻的状态

④Transfer 移交/转移
资源状态的表述在web的各个组件中移交。
在REST的中文版初版,Transfer被翻译为转移。2013修订版中,改为了移交。这两个翻译的意义比较接近,”移交”可能更细致严谨,但”转移”更顺口。其实无论用哪一个都不会造成理解上的偏差

Representational State Transfer 最终理解
(摘自李琨-什么是资源?什么是资源的表述?)
客户端应用与资源的交互,是通过资源的 “representation”(表述) 来间接完成的。资源的表述是一段对于资源(在某个特定时刻的)状态的描述。
客户端请求资源的表述,对表述加以修改,然后将修改过的表述发送给服务器端,请求服务器端对资源执行某种(局部的或者完全的)状态改变。
在客户端-服务器端之间转移的,并不是资源本身,而是资源的表述。缩写词REST中的“state transfer”翻译为“状态转移”,在客户端-服务器端之间转移的资源表述,所代表的正是资源的当前状态。
资源的表述,可以有多种格式,例如json/xml/html/纯文本等等。服务器发送给客户端的资源表述的格式,可以通过定义在HTTP协议中的标准的内容协商(content negotiation)机制来确定。


论文摘要

摘自论文中的《论文摘要》


REST架构约束

REST架构约束在第5章进行描述,这也是整篇论文的重点

如上图标识处,这是一个混合架构风格,所以以下约束并不全是REST所特有的 (REST区别于其他架构风格的核心特征是第四个约束-统一接口)。
这个混合架构风格中的几种风格约束,除REST特有的之外,都在第3章进行了详细描述,每条非特有约束在论文中也明确指出了是取自第3章的描述中的哪一个风格

一、Client–server:客户端-服务器

论文原文 5.1.2 Client-server

3.4.1小节

“客户端-服务器”,即C/S架构,它表示客户端和服务器是两台分立的机器,这在基于网络的应用的架构风格中最为常见

在Web工程上,用的最多的客户端是浏览器,也就是B/S架构,它也属于C/S架构,是C/S的变种。

【延伸阅读】【REST系列】C/S(B/S)架构和web“前后端分离“的联系 ——‘C/S‘约束知识扩充

网络是基于C/S架构的,这条约束重在表示REST是一个网络风格的架构,同时强调分离用户界面和数据存储这两个关注点,使组件可以独立进化。

论文这段话最不好理解的是 “改善了用户界面跨多个平台的可移植性”。我尝试解读一下
可移植性是指,如果计算机程序可以在创建它的操作系统以外的操作系统中使用而无需进行重大返工,则可移植性是一种计算机程序的特性。移植是完成使计算机程序在新环境中运行所需的任何工作的任务。
跨平台移植最典型的当属java(一次编写、到处运行)。用户界面跨平台移植意味着,用户界面也可以做到一次编写就能部署到多个平台。这将促使客户端与服务器分离,且要求客户端具备相当的独立进化能力。然后,C/S的联系仅仅依靠网络接口,只要不改变接口,二者可以任意进化。
如今的跨平台用户界面开发框架有:Flutter、electron、uniapp等等

与这个约束相对的,即非C/S架构,客户端和服务器不是分立的机器。非C/S可以理解为(参考知乎):在电脑上用某视频播放器看本地磁盘上的电影。这就不是C/S架构,它和网络没有任何关系

二、Stateless:无状态

论文原文 5.1.3 Stateless

3.4.3小节

客户端负责维护应用状态和会话状态,服务器维护资源状态。
通信必须在本质上是无状态的,因此从客户到服务器的每个请求都必须包含理解该请求所必需的所有信息,不能利用任何存储在服务器上的上下文,会话状态要全部保存在客户端,服务器端根据这些状态信息来处理请求。

这个约束产生了可见性、可靠性和可伸缩性三个架构属性,使分布式系统更加健壮。但也因为设计上的权衡 而存有一些不那么重要的缺点(不需要考虑)

优点

  1. visibility:可见性、透明度。系统无需通过请求内容以外的信息判断请求的完整内容
  2. reliability:可靠性、稳定度。在部分失败的情况下,减轻了恢复的难度
  3. scalability:可伸缩性、伸缩度。无需储存请求间的状态使服务器端可以很快释放资源并简化实现。增加了水平拓展的便利性

缺点

  • 降低网络性能:因为请求需要传送额外的数据,让服务器能足够理解这个请求。比如每次都要带那么一堆Request-Header
  • 降低服务器对于同种请求进行处理的控制能力:“将应用状态放在客户端还降低了服务器
    对于一致的应用行为的控制能力,因为这样一来,应用就得依赖于跨多个客户端版本
    (semantics across multiple client versions)的语义的正确实现” 这句话经过了一些思考和讨论,也没有明白作者的意思。(如果有大神理解可以放在评论中) 不过即使不理解这个缺点,也完全不妨碍理解REST,因为在设计的权衡点中,缺点是次要的

【附】【REST系列】关于session不遵守REST‘无状态约束‘的解决方案 ——REST‘无状态约束‘知识扩充

三、Cacheability:缓存

论文原文 5.1.4 Cacheability

客户端和中间的通讯传递者可以将服务器的回复缓存起来。回复必须明确的或者间接的表明本身是否可以进行缓存,这可以预防客户端在将来进行请求的时候得到陈旧的或者不恰当的数据。管理良好的缓存机制可以减少客户端-服务器之间的交互,甚至完全避免客户端-服务器交互,这进一步提了高性能和可扩展性。

————
以上几条约束都取自 已有的web架构风格,接下来就是REST特有的、对早期Web架构进行扩展的约束

四、⭐Uniform Interface:统一接口 (RESTful API)

论文原文 5.1.5 Uniform Interface
这是REST的核心特征

这条约束引出了”四个接口架构约束“,它们可以实现所有组件之间统一的接口,可以指导组件的行为、简化整个系统架构并提高交互的可见性(透明度)。

①资源的识别:接口能够标识客户端和服务器交互中涉及的特定资源。例如使用URI标识资源

②通过表述来操作资源:客户端得到资源的表述时,能够有足够的信息来修改或删除服务器上的资源,如果它有权这么做的话。

③自描述的消息:每个消息都包含足够的信息来描述该消息 以支持中间组件的处理。例如HTTP使用标准的方法(PUT|DELETE…)和媒体类型(content-type)来表达语义和交换信息。响应还可以明确地表示其可缓存性(Cache-Control)。

摘自5.3.1小节

6.3.2小节还有对HTTP自描述信息的更详细描述

④超媒体作为应用程序状态的引擎(HATEOAS):请求REST资源返回的表述不仅包含资源数据,还包含指向其它相关资源的超链接。这样一来,REST的应用程序(客户端)只需要硬编码一个初始的URI,就可以动态地使用服务器返回的超链接来发现它需要的所有可用资源。HATEOAS实现了用超媒体(超链接)驱动客户端的状态(用户进行的操作),HATEOAS提供了资源的可发现性。简单地说,客户端完全通过服务器动态提供的响应与RESTAPI进行交互。说的更简单些,你不需要任何文档或其它外部信息来使用REST API

这四个接口约束,体现出了REST面向资源的核心思想(很像Unix”一切皆文件”的哲学思想)。

本节描述的接口,就是我们平时所说的 RESTful API

————

HATEOAS的详细解释

HATEOAS更简单的意思是 用超链接(超媒体的核心是超链接)驱动客户端的状态
客户端状态。可以理解为 受用户的行为产生的客户端属性。例如当用户触发某个链接,客户端的界面就随之发生了变化,这也叫做客户端的状态随之发生了变化。界面是最直观的肉眼可见的状态,但状态不只包含界面。
这些可使用的链接是服务器动态响应到客户端的,而不需要用户输入或客户端硬编码。当所有的接口都这么做,那么整个客户端状态就实现了超链接驱动

类比。HATEOAS类似于人类web用户访问网站的主页(REST的客户端就像浏览器),用户只需要记住主页的地址,就可以通过主页展示的各个超链接进一步访问网站的资源。

作用。HATEOAS最重要的一个作用是松耦合。如果REST服务的调用者需要对所有资源URI进行硬编码,那么这些URI与程序是紧耦合的。而HATEOAS实现的动态URI与程序是松耦合的。

示例。wiki-hateoas中有一个典型的示例。客户端请求一个账户信息的接口,不仅会获得账户详情,还会获得一组href,它包括存款、提款、转账等URI。如果账户已透支,则href只包含存款。

// REQUESTGET bank.example.com/accounts/12345 HTTP/1.1// RESPONSEHTTP/1.1 200 OK{    "account": {        "account_number": 12345,        "balance": {            "currency": "usd",            "value": 100.00        },        "links": {            "deposits": "/accounts/12345/deposits",            "withdrawals": "/accounts/12345/withdrawals",            "transfers": "/accounts/12345/transfers",            "close-requests": "/accounts/12345/close-requests"        }    }}// RESPONSE (overdrawn)HTTP/1.1 200 OK{    "account": {        "account_number": 12345,        "balance": {            "currency": "usd",            "value": -25.00        },        "links": {            "deposits": "/accounts/12345/deposits"        }    }}

应用。spring提供了一个HATEOAS框架:Spring HATEOAS、指南-构建超媒体驱动的 RESTful Web 服务

缺点。

  • 缺乏安全性。客户端根据响应来动态地调用后续API,但这么做具有盲目性、不可控性,也就意味着不安全性。你的客户端不能保证能够适配现在以及以后的API,你不能保证充分测试,因为它们是动态的。如果服务器对客户端是不可信的,那么动态API会更加危险。
  • 无法丰富描述。随着web的发展,某些API可能无法依靠这种简单的方式调用,比如微信/支付宝/PayPal的支付接口,他们需要提供图文文档来让调用者理解和掌握这套API。
  • 所以目前HATEOAS并不流行(我没有发现有哪个系统使用了HATEOAS)。当然,也可能是人们还未发现让HATEOAS变得可靠易用的方案

五、Layered System:分层系统

论文原文 5.1.6 Layered System

3.4.2小节

论文对这条约束描述的很细致。

分层系统带来了客户端和服务器的中间组件(简称中间件),如代理、网关、web服务器、消息中间件、缓存服务等。它们能够为客户端与服务器的交互带来帮助,如提供负载均衡、安全性检查、消息缓存等等。
很多中间件都发展成了成熟的开源项目,系统架构开发中经常会用到。

分层系统简化了每个组件的实现,为整个系统的复杂性设置了边界,提高了系统的可伸缩性。和CS约束(第一条约束)一样,这种分层更进一步增强了各组件的独立进化。

分层系统的唯一缺点是 增加了数据处理的开销(要经过多个组件) 和 组件通信带来的延迟,因此降低了用户感受到的性能。如果系统架构能够支持缓存,可以通过缓存来弥补这个缺点。

六、Code-On-Demand:按需代码 (可选)

论文原文 5.1.7 Layered System

3.5.3小节

这条约束表示 服务器可以向REST客户端添加拓展功能,通过发送可由该客户端执行的代码。例如 客户端脚本,如JavaScript;或编译的组件,如Java applet。

举个例子来更好地理解这一点。
例如,一个网络浏览器就像一个REST客户端,服务器传递HTML内容,浏览器进行渲染。在服务器端,有某种服务器端语言,在服务器端执行一些逻辑工作。但是,如果我们想添加一些在浏览器中工作的逻辑,那么我们(作为服务器端开发者)可以向客户端和浏览器发送一些JavaScript代码,然后执行这些JavaScript …

这种做法能够为一个已部署的客户添加功能,提升可扩展性和可配置性。但它降低了系统的可见性(透明度),如果客户端无法信任服务器,这会导致明显的客户端安全问题。所以这是REST可选的约束。

什么是RESTful?

ful是形容词后缀,RESTful表示REST式、REST形式的、REST样子的

任何遵守REST约束的系统都被称为RESTful(Rest式)架构

wiki-REST (这里在描述上仅限定于Web服务是不客观的)


Roy Thomas Fielding 博士 (作者简介)

Fielding的这篇论文是Web发展史上的一个重要的技术文献,值得每一位web乃至internet工作者阅读。”—— 如果仅仅这么说,大家可能并不会在意它。

为了让我们重视REST,知道它的价值。就不得不了解论文的作者 —— Roy Fielding

这是Fielding的个人网站:Roy T. Fielding

自1993年以来,Fielding一直积极参与万维网项目。他建立了最初的UCI-ICS的万维网服务器,创建了一些万维网软件包(libwww-ada95、libwww-perl、MOMspider、wwwstat)

并在1994年初通过IETF的URI、HTTP和HTML(用于检索和查看本文档的一组协议)工作组参与了指定和改进万维网基础设施的工作。成为了URI和HTTP(HTTP1.0和HTTP1.1)的主要设计者

Fielding还是Apache基金会的第一任董事会主席,是Apache HTTP服务器的主要设计者。Apache HTTP服务器如今在在web服务器中依然占主导地位。

当然,Fielding还创作了这篇论文,即《Architectural Styles and the Design of Network-based Software Architectures》(架构风格与基于网络应用软件的架构设计)。这篇论文主要研究现代网络架构设计的原理,以及它与其他建筑风格的不同之处。

因此Fielding博士可谓是Web架构的奠基者之一

REST论文,其实就是Fielding以Web设计者的视角,描述了Web架构应该是什么样子的。在论文的最后一章(第六章),Fielding还描述了把REST应用到HTTP和URI这两个Web最重要的技术。


REST与Web、HTTP、URI

论文的最后一章(第六章) 描述了 把REST应用于HTTP和URI两个Web规范。
HTTP和URI是Web的两大重要技术。REST是为超媒体系统设计的架构,Web是最大的超媒体系统。所以将REST应用于HTTP和URI是非常有必要的论题

下图划出了第六章的一些重点,可以快速领悟REST和Web的联系

可见,REST论文虽然是2000年发表的,但实际上在1994年就已经被构思出来,用于指导Web架构规范的设计和开发,并在这些实践中不断地迭代和完善。

2000年这个时间点也值得琢磨,因为它正好是HTTP1.1发布的一年后(HTTP1.1在1999年发布)。让人不自觉联想:或许这表示REST和HTTP都已经走向了成熟阶段。

REST应用于URI的体现:REST 对于信息的核心抽象是资源。REST为URI规范定义了”资源”这个术语,以至于URI的设计与REST的”资源标识符”这个架构概念相匹配。

这几句话都来自论文

REST应用于HTTP的体现:REST的约束体现在HTTP中

REST约束HTTP
CS网络是基于C/S的,C/S是网络协议最基础的特性,HTTP是网络协议
无状态HTTP是无状态的协议
缓存HTTP1.1新增了缓存处理cache-control字段。通过设置字段cache-control来控制缓存。当浏览器请求资源时,先看是否有缓存的资源,如果有缓存,直接取,不会再发请求,如果没有缓存,则发送请求。
统一接口资源的识别:HTTP使用URL标识资源
自描述的消息:HTTP1.1新增了五种请求方法OPTIONS、PUT、PATCH、DELETE、TRACE 、 CONNECT 用于实现自描述的消息

————

总结:REST是为超媒体系统设计的架构,Web是最大的超媒体系统。HTTP和URI是Web的两大重要技术,REST指导了HTTP和URI的设计和开发。如此形成了一个闭环设计,最终构成了如今的Web


RESTful API 设计

使REST架构风格区别于其它基于网络的架构风格的核心特征的是 REST的第四条约束 “统一接口”(Uniform Interface)。它强调了所有组件之间要有一个统一的接口。这个接口可以指导组件的行为、简化整个系统架构并提高交互的可见性(透明度)。

这个”统一接口”,就发展成了今天的 RESTful API,即REST风格的接口。

RESTful API 有一个非常精辟的解释:就是用URL定位资源,用HTTP动词(GET|PUT|POST|DELETE|...)描述对资源的操作

来自知乎-怎样用通俗的语言解释REST,以及RESTful? – Ivony的回答

这句话非常适合入门者快速领悟并运用 RESTful API 。

Richardson Maturity Model

“用URL定位资源,用HTTP动词描述对资源的操作”。这句话非常适合入门者快速领悟并运用 RESTful API 。普通玩家可以止步于此了,专业玩家请继续。

但句话的确精辟,但不是RESTful API的全部。熟读论文的朋友应该知道,REST的统一接口约束引出了四条接口架构约束,分别是:资源的标识、通过表述来操作资源、自描述的消息、超媒体作为应用状态的引擎(HATEOAS)。”用URL定位资源,用HTTP动词描述对资源的操作”显然没有做到全部

于是我们引出 Richardson Maturity Model (RMM) 理查森成熟度模型。

该模型来自于 2008年11月20日,Leonard Richardson在QCon的演讲Justice Will Take Us Millions Of Intricate Moves的第三幕The Maturity Heuristic。
后来被Matin Fowler进行了进一步地、更简洁的的解释(原文-Richardson Maturity Model),并把它叫做 Richardson Maturity Model

RMM根据Web API对模型四个层次的遵守和符合情况进行分类,该模型的研究是为了找出REST和其他形式的网络服务之间的制约关系。
该模型将RESTful设计的原则部分分为三个步骤:资源识别(URI)、HTTP动词和超媒体控制(HATEOAS)。
RMM可以用来确定一个Web服务架构对REST原则的遵守程度,特别是评估RESTful Web API设计的质量。它将Web API分为四个级别(从0到3),每一个更高的级别都对应着对REST设计的更全面的遵守,下一个级别也包含了前一个级别的所有特征。

第一层 | Level 0: The Swamp of POX (POX沼泽)
这是该模型的起点。它仅仅使用HTTP作为远程交互的通信隧道。本质上,这个层级所做的是使用HTTP作为远程过程调用(RPC)的一种具体形式。

这是一个简单直接的RPC风格的系统,消息的传递是以POX(Plain Old XML)、JSON或其它文本格式进行的。
(LV0的名字中仅提到了POX,而没有JSON或其它文本格式。可能是因为当时主流XML格式,比较典型的是SOAP)

Lv0层级的系统不归类于RESTful

第二层 | Level 1: Resources (资源)
在RMM中实现REST的第一步是引入”资源”,URL是资源的抽象标识。因此,现在我们不再向一个单一的服务端点发起请求,而是开始与各个资源对话。

这与单纯的RPC产生了区别,就像是编程语言中的面向过程和面向对象。引入资源后,请求不再是单纯调用一些函数并传递参数,而是在一个特定的对象(资源)上调用一个方法,为其它信息提供参数。

这是一种思维的转变。REST对信息的核心抽象是资源,Web组件的交互就是对资源的操作

第三层 | Level 2: HTTP Verbs (HTTP动词)
从这层开始使用HTTP动词和HTTP响应码进行交互,使其接近于HTTP本身的使用方式。

HTTP的请求动词,最常用的有四个

  • GET:用于获取资源。比如查询用户信息
  • POST:用于创建资源。比如创建用户
  • PUT:用于更新资源。比如更新用户信息
  • DELETE:用于删除资源。比如删除用户

HTTP的响应码,常见得有

  • 200:表示请求成功
  • 302:表示重定向
  • 403:表示没有权限访问
  • 404:表示找不到URL对应的资源
  • 500:表示服务器出错了,完成不了这次请求

正确地使用HTTP请求动词和响应码是至关重要的。比如,HTTP将GET定义为一种安全操作,即它不会对任何东西的状态做任何重大改变。这允许我们以任何顺序安全地调用GET,每次都能得到相同的结果(只要资源不发生改变)。这样做的重要作用是,它允许请求路由中的任何参与者(组件、Web基础设施)使用缓存,这是使网络表现良好的一个关键因素。通过遵守HTTP的规则,我们能够利用这种能力。

第四层 | Level 3: Hypermedia Controls (超媒体控制)
最后一层介绍了超媒体控制,即实现HATEOAS,这在前面描述REST”统一接口”时有详细介绍(如果记不清应该回去再看一遍)

请求REST资源返回的表述不仅包含资源数据,还包含指向其它相关资源的链接。这些链接存在于响应消息中的专门部分,它的重点是告诉我们下一步可以做什么,以及我们需要操作的资源的URI。

这么做的优点包括无需在客户端中硬编码大量的URL,起到松耦合的作用。
(正如前面在描述”统一接口”时那样,我认为HATEOAS的缺点也比较明显,存在安全性和无法丰富描述接口的缺点。可能是因为这样,HATEOAS并没有流行起来,准确地说是我没有看到哪个系统在用HATEOAS)

这是Richardson Maturity Model的最后一级。

将版本号用于RESTful API

假设你设计了一个网站,前端和后端都是你写的,如果某个后端API调整了,因为前端也是部署在你的服务器上,所以你可以很方便的对前端对应的这个API调用文本进行更换。
但这么做仅限于一个单纯的网站系统。如果客户端并非只有网页,还包括用户下载的桌面应用、或你的API作为第三方API提供给其它人使用。那么你无权修改这些客户端编码的API。你需要对原有的API返回一些警告,并为想要进行的调整用一个新的API提供。

随着技术和环境的发展,API必然不能在出生时就完全确定下来,一直不变,否则它们会很难进化。将版本号应用于API,就成了一个必要性的需求。

RESTful API 中使用版本号,主要有两种形式:一种是把版本号放置在URL中,一种是把版本号放置在HTTP Header中。(参考RESTful API进行版本控制)

把版本号放置于URL,无论对API提供方还是调用方来说,都是最直观、简洁、简单的一种。

将版本号放置于URL,在一定程度上会干扰对”用URL标识资源”的遵守和理解。但它确实是最简单有效的方式。

注意:版本号应当尽量地被用来 保障 对操作资源的参数的演变。在API设计之初,应当努力将信息抽象为资源,使其符合RESTful,而不是日后让版本号来承担API设计风格上的错误。版本号不是对API设计上的放纵,不应该因为有版本号而在一开始就随意地设计API

应用实例- 微信支付接口

  • 微信支付接口的老版本(v2),这时候还不是 RESTful API

  • 最新的v3版本,已经采取了RESTful API。相比旧版更加清晰明了。并可以看到URL采用了版本号标识v3

应用实例- PayPal支付接口


⭐把书读薄 – 要点总结

① REST的定义:为分布式超媒体系统设计的一个混合式架构风格

② REST和Web的联系:Web是世界上最大的分布式超媒体系统,所以REST适用于Web。并且作者在第六章表示,REST从从设计之初就是为了指导Web架构的设计和开发。

之所以REST在定义上没有指定Web,是因为REST具有通用性。松耦合和通用性是架构师的两个设计原则,Fielding也一样。

③ REST和其它网络架构的区别:REST是一个混合式架构风格。”CS、无状态、缓存”这三个约束是从早期网络架构中借鉴来的。”统一接口、分层系统、按需代码(可选)”是REST特有的,其中”统一接口“是REST区分于其它网络架构的核心特征。统一接口延伸出了RESTful API,所以很多人对REST的理解就是使用RESTful API,对于一个单纯的使用者来说,这无可厚非。

④ REST的核心面向资源是REST的核心。正如5.2.1.1所说,REST对信息的核心抽象是资源

⑤ Fielding是Web架构的奠基者之一:Fielding即是REST的作者,又是Apache HTTP服务器的主要设计者,还是URI、HTTP的主要设计者。所以Fielding对Web的理解应当是深刻的,REST论文值得所有web开发者重视

⑥ REST和HTTP:目前为止,HTTP依然是实现REST的最佳选择,毕竟HTTP是受REST指导而设计的。不过,HTTP1.1开始才真正符合REST架构思想。这也是HTTP1.1发布后,REST才发表的原因之一吧。(HTTP1.1于1999年发布,REST论文于2000年发表)