会员登录 - 用户注册 - 设为首页 - 加入收藏 - 网站地图 一篇带你理解Restful风格!

一篇带你理解Restful风格

时间:2025-11-05 11:44:05 来源:益强数据堂 作者:应用开发 阅读:539次
REST是篇带什么

REST从2000年被Roy Fielding提出距今已有20多年,其对Web技术产生了深远的理解影响。REST本身并没有产生新的篇带技术或者中间件,REST传递的理解是一种设计思想,其提供了一种约束原则和条件。篇带

REST全称为Representational State Transfer,理解中文为表征性状态转移,篇带感觉前面其实还少了一个主语“资源”,理解个人理解应该是篇带“资源表征性状态转移”。而其核心就是理解通过创造一种资源的定义与描述原则,形成一种标准化规范,篇带从而减少技术人员在开发与沟通时候的理解成本。

实现REST风格的篇带框架叫Restful架构时,而我们主要是理解使用的HTTP作为这种规范的载体,本文也是篇带针对HTTP的形式来进行讨论。但我认为,只要满足REST设计思想的功能描述方式,都可以算作REST的站群服务器实现,其并不局限于HTTP协议。

理解REST

Representational State Transfer,其实已经将REST的整体概念罗列出来了,加上我们补充的主语“资源”,可以很明确的体现出REST中主要的两个概念:

资源,资源表征动作,状态转移

简单理解的话,REST是就是将一个接口动作的描述进行拆分,拆分成资源与动作两个部分。其中,资源就是对描述资源位置,资源表征则是这些资源应该如何展示出来(具体是JSON还是XML),而状态转移则可以简单的理解成正对这个资源所进行的动作。

REST的正是通过将这两种核心定义的逻辑进行分离、标准化,企商汇从而让对于“接口”、“操作”的定义更加便于理解,和可阅读(更完成权威的介绍可以参考:

https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)。

资源

REST中的核心概念之一是对资源的的描述,而这个资源是一个抽象概念,并不一定是一个静态的资源,也可以是完整资源的一部分。实际上,只要是可以被引用的部分,我们都可以称之为一个资源。

而在web中我们标识一个资源使用的是URI(Uniform Resource Identifier)。从定义上来讲,URI是唯一标识符,即可以说是资源的名称也可以说是资源的WordPress模板地址。从这个角度上来说如果无法用URI来表示一个内容,那么就不能说它是一个资源。

一些正面的例子:

https://blog.csdn.net/losorick/article/details/123311537。

https://xie.infoq.cn/article/3ddce663b21acd89f41582aa3。

一些反面的例子:

/export/create。

资源定义中多个名词之间用"-"(最好不用用"_",会在特定情况下显示不完全)来进行分割,并用"/"来表示资源增肌的概念。也可以用","或者";"来作为多个资源的分割。当然这些都是建议建议,对于具体的实施只要项目中统一就行,比如github中就是使用"..."来作为多个资源的分割,例如“/git/git/compare/master…next”。

资源表征

URI只定位了具体的资源,但对于客户端来说是这是一个统一的抽象。如果客户端要使用的话并不能直接使用,需要指明所需要使用的资源形式。当前主流的文本交互方式表征是JSON格式,当然对于要求响应格式严谨的团队来说仍然有使用XML格式的,而对于媒体资源来说也有PNG、MP4等形式。

原则上,资源定位符只负责资源的标识,但是并不关注具体怎么展示资源,而需要用何种形式展示资源则是由客户端根据自己的需要申请的。在HTTP中我们服务端通常使用“content-type”来对资源的表征来进行描述,而客户端则是用“Accept”请求头中来指明所需要的格式类型。

同时,资源的表征并不局限在资源的输出类型上,资源间的关联关系也是资源表征的一部分。举例而言,当我们查询一个详情信息,查询后的响应体本身是一个资源,用于描述这个详情信息。如果需求要我们描述这个详情信息后的下一个详情信息的访问链接,用于提示用户进一步浏览。这个信息“下一个链接”的信息,如果我们放到响应体中似乎并不是很合适,因为这对于一个GET请求来说,这个“下一个链接”信息并不是资源本身的一部分。并且随着系统中推荐算法的运行,这部分信息甚至变成不可缓存的内容(因为可能随时发生改变)。基于以上讨论,或许我们增加一个LINK响应头用来描述“下一个链接”的信息,就达到了目的并保证了响应体对于资源本身描述的正确性。

所以,资源表征并非是对数据库的CURD,它体现了资源作为一个超媒体中一部分的这个概念(资源与资源的连接关系)。同时我们可以使用HTTP中的各个部分来独立的描述各种概念,而非一股脑的都丢到响应体中。

状态转移

通过上文中的描述,我们可以将资源理解成了一种静态的内容。那么该如何理解我们对资源的操作呢?REST是用状态转移来表述这件事的。当我们新建一个资源时,就将资源从“无”状态转移为了存在状态;当我们更新一个资源的时,则是让其内部的状态发生了更改。

REST中的是使用HTTP方法来描述这些操作类型的,这样的好处是,我们可以为操作类型指定统一的规范。举个例子来说,在REST中所有的GET请求都应该是可以被缓存的,所有的PUT请求都应该是幂等的。我们通过将接口操作约束成明确的HTTP方法或者是其他统一方式,从而减少在接口对接查看时的沟通成本。

常用的HTTP方法主要是:GET、POST、PUT、DELETE。但是更早版本的客户端可能只有GET和POST。而根据协议的升级则支持LOCK、UNLOCK等方法以及自定义方法。但通常企业内会根据自己的主要受众设备进行调整这些设计。

从Restful出发的接口规范

对于一个接口,其中的URI部分应该只用于描述操作时针对哪个资源的。而“HTTP方法”应该才用于解释操作的类型的。但是企业中如果要推行REST接口的规范的话,仍然有一些问题需要调整确认,原因可能是内部历史原因或者当前框架与REST并不适配,本小节举例其中的两个例子用于各位参考。

向下兼容

由于在业务实际开发的过程中,可能会出现业务的逻辑变更,我们处理这种问题的主要方法就是通过对接口添加版本信息来实现的。

但是由上文可知,URI本身应该用于定义资源的名称和地址。所以对于同一个资源来说,内容变了就是变了,资源本身是没有版本的概念,我们实际上调整的是资源的不同的表征方式,而这个方式才对应的“版本”的概念,而非资源本身。如果是从这个角度出发,对于REST的设计来说,这个版本的概念就不应该出现在URI的资源定位符上,因为资源的名称都是同一个。那么对于REST我们可以通过在Accept响应头追加版本信息(version)来区分具体的表征方式。例如:

Accept: version=1.0。Accept: version=2.1。Accept: version=3.0。

但是在实际的企业中,我们通常不会这么做。原因有很多,其中一种是因为在业务沟通的时候,通常只聚焦在URI和HTTP方法上。在实际沟通中我们将URI和HTTP方法作为互相沟通的主要方法,并可以通过一行就表示出全部信息,例如:

{GET} http://api.example.com/trade/order/1。

所以如果在URI地址上直接添加版本信息,就可以通过以下方式表示:

{GET} http://api.example.com/trade/v1/order/1。{GET} http://api.example.com/trade/v2/order/1。{GET} http://api.example.com/trade/v3/order/1。

这样的好处就是可以通过URI直接描述兼容性信息,而缺点就是破坏了REST原教旨主义的资源定位方法。但REST推出到当前已有20多年时间,而实际业务中“资源”数量也已经爆炸数量增长。所以在服务治理等各种新概念成为必要需求的今天,符合现状的调整才是合适的。

定制的操作

在REST中我们需要用HTTP的方法来定义操作的类型,那么就有一个主要问题:已有方法无法描述当前操作怎么办。一些常见的操作(Postman中有的)是PATCH(github有)、COPY、LINK等。除此之外常见的还有BATCH- CREATE等批量操作。

如果根据REST原教旨主义则应该在HTTP方法中进行扩展,但由于系统兼容性等问题,我们希望保证各种版本的客户端可以对方法进行支持。

首先,不论我们是使用什么方法来表示自定义操作,都需要满足统一表达,并且可以应用在所有的方法中。根据这种情况,本小结列举出几种方案作为参考:

扩展方法

HTTP中的方法可以自己扩展,Github新增了PATCH方法,WebDAV中扩展了LOCK、UPLOCK等方法,但这些都不是HTTP中的标准方法,如果使用该方法需要考虑客户端的支持能力。

参数定义

通过使用预留参数定义扩展方法,例如使用_method=DELETE来对请求方法来定义,并在服务端对具体方法进行路由。这种方法的好处是可以将参数代入到URI中,并不影响URI原版本的资源定位的意义。

URI后缀描述

可以通过在URI添加后缀来描述动作,例如在后缀添加/actions:delete来定义,或者在URI最后使用/actions标记,并在请求体中第一层来描述扩展的动作类型。这样虽然导致URI定义中加入了额外的资源地址之外的额外信息,但是可以保证整体访问接口中的信息是完整的。

总体来说,对于确定定制操作的扩展方案要在客户端支持成都、下游网关改造难度以及接口可读性中做出平衡。

Restful风格的问题

使用Restful风格的构建项目中主要需要的问题就是关于path-variable的处理问题。在一些项目治理项目中默认是认为有path-variable引起的不同path是不同的URL,所以无法直接使用,需要具有开源软件二次开发的能力和需求。

举一个Sentinel的例子,Sentinel是根据url生成的资源名称,而因为REST中用path-variable来定义资源,所以就导致了同一类资源的定义符被识别成了不同的资源。

但随着查看Sentinel中的代码我们可以发现,Sentinel中默认使用CommonFilter来处理请求的url,并且主要是通过UrlCleaner接口中的clean方法来对资源进行重命名,所以我们可以通过重写clean方法实现满足rest的资源明明问题(事实上官方也提供了

sentinel-spring-webmvc-adapter来支持rest风格定义的接口)。

由于REST风格是主流的接口规范风格之一,所以使用量较大的中间件一会都会有对应的解决方案,但是对于自研的工具需要考虑REST风格的兼容性,可以参考一些开源软件如Swagger的匹配来实现。

最后

本文讨论了REST中的相关概念,并非完全照本宣科的进行陈述,如REST的6大指导原则也并没有介绍。REST本身是一个比较大的概念,但是在如今前已经后端分离、微服务化等概念逐渐普及,原本的REST概念并非完全的适用。但是REST的核心理念对我们的接口规范设计有十分重要的指导性意见。

(责任编辑:数据库)

最新内容
推荐内容
  • 有些Linux用户在使用了Ubuntu系统后,不知道该怎么安装Visual Studio Code,今天小编就帮你解决这个问题吧,下面就是具体的安装步骤了。安装方法:安装过程中,将会询问安装路径,如下图:经过一系列要求和条件后,询问你是否确认安装Visual Studio Code。输入“a”来确定:确定之后,安装程序会开始下载并安装。安装完成后,可以发现Visual Studio Code图标已经出现在Unity启动器上。下图是Ubuntu 15.04 Unity的截图:卸载Visual Studio Code,同样使用Ubuntu Make命令。如下:umake web visual-studio-code --remove假如不使用Ubuntu Make,也可以通过微软官方下载安装文件。Download Visual Studio Code for Linux以上就是在Ubuntu系统中安装Visual Studio Code的方法了,还不会安装Visual Studio Code的用户,就参考上面的步骤进行安装吧。
  • 电脑沙发调节高度教程(轻松操作,让您的沙发高度适配您的需求)
  • ubuntu 11.10输入法图标不显示的解决   问题:   今天更新了ubuntu。结果重启机器之后输入法的图标不显示了。   输入法的切换效果还是有的(只是不没有显示图标)。   Ubuntu11.10下ibus输入法的图标经常消失,输入中文时很不方便。   解决办法:   打开终端,重启一下ibus!   输入:   killall ibus-daemon(结束进程)   ibus-daemon -d(重启ibus)   如下图右上角所示:
  • 关于iptables有价值的信息很多,但是大多都描述的很复杂。假如你想做些基本的配置,下面的 How To 很适合你。 # iptables -L 列出您当前iptables中在规则。假如您是刚刚建立您的服务器,那么可能此时还没有任何规则,而且您应该看到如下: Chain INPUT (policy ACCEPT) Chain FORWARD (policy ACCEPT) Chain OUTPUT (policy ACCEPT) ◆ 允许建立会话 我们可以允许建立会话来接受流量: # iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ◆ 在指定端口上允许入站流量 阻断所有流量您也可以启动系统,但是您可能正在通过SSH工作,所有在您阻断其他流量前有必要允许SSH流量。 为了在22端口号(默认的SSH端口)上的允许流量入站,您可以告诉iptables允许您的网卡接受所有的目的端口为22的TCP流量。 # iptables -A INPUT -p tcp -I eth0 --dport ssh -j ACCEPT 特别的,这将向表中追加(-A)INPUT规则,允许目的端口号为SSH的所有流量进入接口(-i) eth0,以便iptables完成跳转(-j)或动作:ACCEPT 让我们核对下这些规则:(这里仅显示了少数行,您应该看到更多) # iptables -L 现在,让我们允许所有的web流量 # iptables -A INPUT -p tcp -I eth0 --dport 80 -j ACCEPT 检查我们现有的规则 # iptables -L 我们已经指定SSH和web端口为允许通过的TCP流量,但是因为我们还没阻断任何流量,所以到目前为止所有的流量仍然可以进入。 ◆ 阻断流量 一旦一条规则对一个包进行了匹配,其他规则不再对这个包有效。因为我们的规则首先允许SSH和WEB流量,所以只要我们阻断所有流量的规则紧跟其後,我们依然能接受我们感兴趣的流量。大家要做的仅仅是把阻断所有流量的规则放在最後,所以我们需要再次用到它。 # iptables -A INPUT -j DROP 因为我们刚才没有指定一个接口或一个协议,所以除了web和ssh流量外其他任何流量都会被阻断。 ◆ 编辑 iptables 到目前为止我们设置过程中唯一的问题是回环端口(loopbakc)也被阻断了。我们本可以通过指定 -I eth0 来仅仅丢弃eth0上的数据包,但我们也可以为回环端口(loopback)添加一条规则。假如我们追加这条规则,这将太晚了----因为所有的流量已经 被丢弃。我们必须插入这条跪着到第4行。 # iptables -I INPUT 4 -I lo -j ACCEPT 最後2行看起来几乎一样,因此我们可以让iptables列的更详细些。 # iptables -L -v ◆ 日志记录 在上面的例子中,所有的流量都不会被记录。假如您愿意在syslog中记录被丢弃的包, 下面将是最快捷的方式: # iptables -I INPUT 5 -m limit --limit 5/min -j LOG --log-prefix iptables denied:  --log-level 7 看 提示 段获得更多关于logging的ideas. ◆ 保存 iptables 假如您现在要重新启动机器的话,您的iptables配置将会消失。为了不用每次重新启动时敲入这些命令,您可以保存你的配置,让它在系统启动时自动启动。你可以通过iptables-save 和iptables-restore命令来保存配置。 保存您的防火墙股则到一个文件 # iptables-save >/etc/iptables.up.rules 接着修改 /etc/network/interfaces 脚本自动应用这些规则(末行是添加的) auto eth0 你也可以准备一组规则冰并自动应用它 auto eth0 ◆ 提示 下面的步骤复习了怎样建立你的防火墙规则,并假定它们相对固定(而且对于大多数人来说它们也应该是)。但是假如你要做许多研究工作,你也许想要你的 iptables在你每次重启时保存一次。你可以在 /etc/network/interfaces 里添加像下面的一行: pre-up iptables-restore < /etc/iptables.up.rules post-down iptables-save >/etc/iptables.up.rules 此行将保存规则用于下次启动时使用。 假如你超出了这个指南来编辑iptables,你可能想利用iptables-save和iptables-restore来编辑和测试你的规则。你可以通过使用你喜爱的文本编辑器(此处为gedit)来打开这些规则文件来完成编辑。 # iptables-save >/etc/iptables.test.rules 你会得到一个如下类似的文件(下面是紧接上的例子文件): # Generated by iptables-save v1.3.1 on Sun Apr 23 06:19:53 2006 注意到这些都是减去iptables命令的iptables语句。随意编辑这些命令、完成後保存它们。然後简单的测试下: # iptables-restore < /etc/iptables.test.rules 测试完毕後,假如你还没添加iptables-save命令 到 /etc/network/interfaces 里面,记得不要丢失了你的更改: # iptables-save >/etc/iptables.up.rules ◆ 更详细的日志 # Generated by iptables-save v1.3.1 on Sun Apr 23 05:32:09 2006 请注意 一个名为 LOGNDROP的链在文件顶部。而且,INPUT链底部标准的DROP被替换成了LOGNDROP,同时添加了协议描述so it makes sense looking at the log。最後我们在LOGNDROP链尾部丢弃了这些流量。下面的行告诉我们发生了什么: * --limit 设置记录相同规则到syslog中的次数 ◆ 禁用防火墙 假如您要临时禁用防火墙,您可以通过下面的命令清空所偶的规则: # iptables -F ◆ 轻松配置通过 GUI 新手可以利用 Firetarter(一个gui工具)---仓库中的可用软件(新立德或apt-get 获得)来配置她或他的iptables规则,而需要命令行知识。请查看指南,尽管…… 配置很简单,但是对于高级用户来说可能远远不能满足。然而它对于大多数的家庭用户来说是足够的…… 。(我)建议您使用firestarter在策略表中将出站配置为 “限制”,而将您需要的连接类型(如用于http的80、https的443,msn chat的1683等等)加入白名单。您也可以通过它查看进出您计算机的活动连接…… 。防火墙会一直保持下去一旦通过向导配置完毕。拨号用户必须在向导中指定它在拨号时自动启动。 firestarter主页: http://www.fs-security.com/ (再次, 仓库源中可用, 不需要编译) 指南: http://www.fs-security.com/docs/tutorial.php 个人笔记:不幸运的是,它没有阻断(或询问用户)特定应用/程序的选项……。因此,我的理解是一旦启用了80端口(例如,用于访问网页),那么任何程序都可以通过80端口连接任何服务器、做任何它想做的事……
  • 华为畅享7s取卡实用指南(华为畅享7s取卡教程,快速上手使用,解决常见问题)
  • FlowN Play是个用Qt编写的新视频播放器。它有着漂亮又简洁的界面,只提供基本的播放功能。复制代码代码如下:然后下载DEB安装包,可以双击或在终端里把正操作的目录换到你保存安装包的目录下并输入以下命令(这个是64位的命令,对于32位的系统请将DEB文件换成32位的):复制代码代码如下:然后在终端里输入flow-n-play来运行它。注意:为防止产生依赖项错误,当你试图安装DEB文件时,你可以运行sudo apt-get -f install,这样可以自动获取丢失的依赖项并安装Flow ‘N Play。复制代码代码如下:第三种方法是手动安装到你选择的地方(在安装完依赖项后下载提供的二进制文件)以32位版本为例:复制代码代码如下:wget -O http://www.prest1ge-c0ding.24.eu/programs/Flow-N-Play/v0.926/bin/Flow-N-Play_v0
热点内容