TOP

作为架构风格的 REST 到底是什么(一)
2020-07-27 06:08:18 】 浏览:40次 本网站的内容取自网络,仅供学习参考之用,绝无侵犯任何人知识产权之意。如有侵犯请您及时与本人取得联系,万分感谢。
Tags:作为 架构 风格 REST 到底 什么

很多人搞不明白 REST(Representational State Transfer 表述性状态转移)原因在于一开始就是把它当做设计风格而不是架构风格来理解,因而一上来就大谈特谈什么 RESTful API,结果是只见树木不见森林。

仅从设计的角度去理解 REST(仅把它作为 API 设计原则),最多仅能理解其资源、表述这些概念,却很难理解状态转移到底是怎么回事。

要想搞清楚 REST,必须透彻理解三个关键概念:资源、表述、状态转移

REST 架构风格提出者和 HTTP 1.1 规范主要设计者都是同一个人 Roy Fielding。事实上,HTTP 1.1 正是 REST 风格的实现,因而认识 REST 最好的方式是从基于 HTTP 的 Web 应用开始。

场景:

我们看一个典型场景。

李小四想在京东上买一部 iPhone。

首先他在浏览器地址栏输入 www.jd.com(当然也可以通过搜索引擎进入),打开京东商城首页,然后在首页搜索栏输入“iPhone”,回车,页面切换到含有 iPhone 关键字的商品列表。

李小四用鼠标点击其中一个商品,进入该商品详情页。

李小四看了看介绍,觉得中意,于是选定颜色、型号、规格、数量,点击“加入购物车”,再点击“去购物车结算“,填写收货人信息、支付方式、开票信息,点击“提交订单”,选择一种支付方式支付并完成订单。

李小四这个人性子比较急,下了单后,每隔一段时间就点开“我的订单”,点开物流信息看看手机到哪了。

终于,手机送到了,李小四从快递员那里签收后,京东立马通过微信给他推送一条货物签收通知,并且附上开票链接。李小四点击进入开票页面,获取一张电子发票。

资源及其表述:

在整个购物过程中,李小四与之交互的是一个叫“京东商城”的 Web 应用——这是 REST 的作用对象。作为架构风格的 REST,其作用对象是一个完整的应用(或者系统)——确切地说是异构的分布式应用——而不是某一两个 API。这样的视角是理解 REST 全貌的关键。

李小四是如何获取到他想要的信息的?跑到卖家仓库去看实体 iPhone?如果这样,就没有 Web 什么事了。李小四在浏览器地址栏输入了一串叫 URL 的东西,然后浏览器就显示出京东商城首页了。

到底什么是资源?

本例中,真正的资源是 iPhone、物流、发票、钱等,但在谈论 Web 的时候,我们说的资源一般不是指这些真正的实物资源,而是指存储在服务器上的特定数据,如这里的 iPhone、订单、物流、发票、账户的数据信息

对于实体 iPhone,我们可以去专卖店看看摸摸,那 Web 上的 iPhone 数据,我们如何找到它,又如何看如何摸呢?

前辈们设计了个伟大的东西叫 URI,你每台 iPhone 不是有唯一编号嘛,那 Web 上这些虚拟的数据我们也以虚拟物品(资源)的方式给它做唯一编号(标识)。虽然是由资源(虚拟数据)的拥有者来给它做标识,但为了统一、通用,前辈们对资源标识做了一些约束(协议),就形成了统一资源标识符(Uniform Resource Identifier,URI),这样便解决了如何找到资源的问题。比如 URL 通过 schema、域名、端口定位到服务器(资源拥有者),服务器内部再通过 path 和其他参数找到并处理资源。

从 URI (URL 是 URI 的一种实现方案)的定义看,它本身就是用来表达资源的,天生就是名词特性,只是在实际使用过程中不知为啥就跑歪了,各种 /pathto/getuserinfo 动词性的 URL 满天飞(个人认为是成也 HTTP 动词,败也 HTTP 动词,更详细的分析见后面)。

资源是找到了,但我们如何跟它交互呢?

如果是在本机,我们可以通过程序直接操作资源(如通过程序指针直接操作内存数据),但 Web 是个分布式环境,指针没那么长,够不到对方的内存怎么办?

于是我们需要在本地(客户端)拥有一份资源的副本。在 C/S 架构中,只有服务器拥有资源本身,其它客户端拿到的都是副本,而且拥有者(服务器)可以决定提供什么样的副本给客户端(提供哪些信息、以什么样的格式提供信息)。

这种带特定格式的资源副本就是资源的表述

作为资源拥有者,服务器当然可以决定提供什么样的表述形式,但正如 URI 一样,如果没有大家都认可的、通用的、被广泛支持的格式,服务器们各说自话,互相语言不通,那万维网恐怕就会成为巴比伦塔了。

于是前辈们又定义了一些通用的资源表述格式,官方话叫媒体类型。Web 上用的最广泛的媒体类型应该是 text/html,其他还有 image/jpeg、application/json、text/xml 等。

一个资源可以有多种表述(多种媒体类型),也就是说客户端(如浏览器)通过一个 URI(如 URL )可以获得该资源的多种表述中的一种。那么客户端和服务器端是如何沟通以在表述形式上达成一致呢?

在 HTTP 中,通过头信息协商。HTTP 有一系列 accept 请求头就是用来干这事的,如 accept、accept-encoding、accept-language。比如 accept: image/webp,image/apng,image/* 告知服务器“我能处理这些媒体类型,你给其中任意一种给我就行”。服务器端响应头 content-type 则告知浏览器该资源表述的确切媒体类型,如 content-type: image/jpeg 表示它是一张 jpeg 格式的图片。

另外,和现实世界一样,Web 上的资源具有集合特性,比如 iphone,并不是指某一个 iphone,而是指 iphone 集合。从中我们得出以下推论:

  1. 用来表示资源的 URI 应该使用名词复数形式;
  2. 对应集合的包含关系(集合中包含子集合),资源具有层级性;
  3. 集合中的元素具有集合范围内的唯一标识,通过在 URI 中带入该唯一标识来定位集合中的元素,如 /iphones/123456。

假设有这样一个 url:http://www.jd.com/mobiles/iphones/123456

首先这里体现了资源的层级性:手机是一个大资源集合,其下包含了 iphone 这个子集合,而通过资源标识 123456 定位到某一个 iphone。

那么,浏览器访问这个 url 时会返回什么呢?

首先取决于服务器端决定提供哪些媒体类型,我们假设服务器端提供了 text/html、application/json、application/xml 和 image/jpeg 类型。

浏览器会决定请求什么类型呢?

如果我们在地址栏输入该 url,浏览器一般会发送如下头部:accept: text/html,... 要求返回 html 文本。但如果我们在 标签里面写该 url,浏览器会发送诸如 accept:image/* 要求返回图片格式——也就是说,取决于我们在哪里用这个 url,这是浏览器的工作机制,也是 HTML 的魅力所在(后面分析超媒体时再详细分析)。

你可能会发现,现实中我们见到的多数不是这样,更可能是这样:

当要访问 html 类型时:http://www.jd.com/mobiles/iphone.html?id=123456(或者是编程语言后缀)

当要访问图片时:http://www.jd.com/mobiles/iphones/123456.jpg

现实中,我们不但在 URL 中写入动词来表达要进行的操作,还写入类型后缀来表达要什么样的媒体类型——这两者都违背了 URI 和 REST 设计

请关注公众号获取更多资料


作为架构风格的 REST 到底是什么(一) https://www.cppentry.com/bencandy.php?fid=97&id=296076

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇设计模式(12) 代理模式 下一篇到底什么才是真正的空间复杂度?

评论

验 证 码:
表  情:
内  容: