在前后端分离盛行的年代,我们后端在设计API接口的时候肯定离不开RESTful架构规则,那什么是RESTful呢?接下来我们来好好介绍一下什么是RESTful
REST是什么
简单来说,REST是一种风格,用英文来说就是style,那它是什么风格呢?是万维网软件架构的风格。“风格”这个关键词是非常重要的,因为它告诉了我们,REST并不是什么协议,也不是什么硬性的规范,它仅仅是一个软件的架构风格而已。这种风格是用来干什么的?很显然,它既然是万威网软件架构风格,它必然是用来架构万维网软件的。换句话说,它就是用来创建网络服务的。
了解了Rest是什么,我们就不禁会问为何叫rest?
下面我先来从字面意思来解读一下rest。
rest 其实并不是休息的意思,这里的Rest也不是一个英文单词,而是Representational State Transfer这个单词的一个简写,是把这几个单词的首字母拼在一起。我们来看一下这三个单词。
Representational
首先是Representational,表示的是数据的一种表现形式,比如Json,XML。这些都是一种表现形式。其实 rest 它对数据的传输格式是不做任何限制的。但值得关注的是,尽管它不做限制,我们在写 rest 最佳实践时还是要用JSON,JSON用的是最多的。
State
第二个单词是State。State的意思是状态,在Rest词组里面,代表是当前的状态或当前的数据。那是什么意思? 比如说我们写了一个用户的接口,那么在这个用户接口的用户列表里面有一些用户的数据,这些都是单个的用户数据,比如姓名、性别等等。这些它其实都是State,都是数据。
可是在Rest词组里面,为什么要用State表示数据?
比如说我们要对数据要进行增删改查。这样数据又变了。在这个变化的每一个阶段里,它都是一种状态,从状态 1 变成了状态2,再由状态 2 变成状态 3 等等,这样依次来改变。用状态来描述数据呢,更好地显示了这些数据是会变化的,会被我们所修改。
Transfer
最后我们再来看一下Transfer这个单词的字面意思是传输在Rest的词组里面,它表示的是数据在互联网上进行传输,比如从服务端传到客户端,是比较容易理解的。
讲完了Rest的字面解释之后,如果你还是对Rest不是很明白也没关系,因为Rest的字面意思其实是很难表达它的一个主要内容的,所以仅仅通过字面意思的一个解读是没办法真正理解Rest的。下面我们可以通过 rest 的 六个限制来详细了解它。
这 6六个限制是 rest 的一个精髓,也是它的重中之重,在很多面试中也会经常被提问到。
限制一:"关注点分离"
我们先来看第一个限制是客户端服务器,也叫C/S架构。C指的就是client,S就是Server。这个限制其实是非常常见的,现在几乎很多软件架构都是基于C/S架构的。值得一提的是,限制的本质其实是一个软件架构思想,叫做关注点分离。
关注点分离
所谓的关注点分离,简单来说就是各扫门千雪,各自管好各自的事情。在这里指的是服务端专注于数据存储,提升了简单性。而前端专注于用户界面,提升了可移植性。在这里面又提到了一些专有名词,比如简单性、可移植性。这些专有名词都来源于Rest 作者,它的博士论文虽然有点难懂,但确实能够很准确地表达 Rest的一个精髓。所以我们在这里运用了这些专有名词,而且会尽量做一些比较通俗的解读。
什么是简单性?
其实就是让服务端的代码更加简单。 为什么要更简单?因为过去的服务端还需要渲染页面,还有数据存储,现在服务端什么都不用管了,它也不用管用户界面,只需要写好数据存储的逻辑就可以了,所以变得更简单了。
什么是可移植?
可移植的一个软件能够很方便的移植到其他平台。为什么在这里说它方便移植?这是因为在过去我们的前端其实在操作系统里面写那些软件,在那个时候前端还需要去管一些数据的存储,一些计算,或者一些很复杂的逻辑。但是现在前端在浏览器里面进行工作,这样我们前端工程师就不需要去管那些复杂的计算了,只需要调用接口来渲染页面就可以了。这样的能力就是调用接口来赋予的,在很多平台其实都支持的,比如手机上,我们通过了这种方式就可以使用浏览器做很多事情了。这也就是前端所说的提高移植性。
限制二:“是无状态”
所谓的无状态是指所有用户会话信息都保存在客户端。这句话的意思也就是所有的会话信息服务端就不再管理了,你也不要想着让服务端去存你的用户信息。我们也都知道http协议是一个无状态协议,其实服务端连你当前的一些状态他根本就不知道,所以也没必要去存一些会话信息了。这也是服务端不管了之后。所以就要客户端每次请求都必须包含所有的信息,不能依赖于上下文信息。
再给大家举个例子,
比如你现在在一个页面里面看一本小说,我们看的是第一页,你要进入小说的下一页,就必须把具体的页数告诉服务端,你不能跟服务端说我要看下一页,下一页的数据服务端根本不知道,因为他不知道你当前是在第几页。你只是下一页,服务端是没办法理解的。所以你这个请求必须包含所有的信息,不能依赖于服务端的一个上下文了。也就是必须要告诉服务端我要进入第二页,就是精准的第二页,你要把这个页码告诉服务端。这个过程就是http的一个无状态性。
无状态的好处是什么?
- 简单性
- 可靠性
- 可见性。为什么说它提升了简单性?服务端不用保存会话,服务端少了很多代码,自然就简单了
为什么说它提升了可靠性?
可靠性指的是一个软件的稳定程度,以及它从一次故障中恢复过来的能力,为什么说它提升了可靠性?因为如果服务端要管理用户会话信息,一旦服务端出错,用户会话信息就会完全丢失,想要恢复过来几乎是不太可能的,所以它的可靠性就会变得很差。这一点也是在之前被吐槽的地方,如果服务端不再管理用户的会话信息,从故障中恢复过来就会变得很容易。
为什么说它提升了可见性?
什么是可见性?可见性指的就是在软件工程中,那些模块儿接口之间的一个透明程度。为什么提升了可见性?因为每次请求都必须包含所有的信息,所以接口之间就会变得更加透明。因为各个之间了解了相互的所有信息,很多信息也都可以传给服务端了,而不是存到服务端,这样就变得更加透明了,可见性也就更高了。
限制三:“缓存”
第三个限制就是缓存。这个限制具体的意思就是指所有的服务端的响应都必须被标为可缓存或不可缓存的。
哪些应用可缓存,有哪些不能缓存?
举个例子,比如前端的 JS、CSS 这些都是静态文件,可以缓存的,请求一次就行了,不用再请求第二次。它们之间的变化可能性不大。比如 jquery 的JS,虽然它可能会改变,但改变的可能性不大,至少一个版本里面它是不会变的,这样就不需要请求第二次了。对于一些动态接口来,经常会变的接口是不能缓存的。如果缓存,用户就会说我明明请求了,但是更新了,还是老样子。
缓存有什么用?
很简单,缓存的作用在减少前后端的一个交互,提升了性能。比如如果没有了缓存,你的一些JS文件,你在加载的时候,每次都从服务端加载,速度会变得很慢。假如缓存在浏览器页面就会瞬间被打开了,用户能感知到性能的一个提升。
限制四:“统一接口”
第四个限制就是统一接口。这个限制是所有限制中最重要的一个。别的限制如果不是在 rest 里面,比如C/S架构,在我们的现实开发中,几乎都是C/S架构,也不一定是rest 的风格。还有一些缓存等等别的风格也可以用到缓存。但是只有这个统一接口突出了rest的这个特点。
什么是统一接口?
我们要分开来看。首先来看统一。所谓的统一是指接口设计要尽可能的统一通用,也就是接口的设计要遵循一个规范,所有的接口都要像学校里面学生穿上校服一样,这样做到统一规范。
这样做有什么好处?
首先它提升了简单性。所有的接口既然都很相似了,那学习起来肯定是很简单的。比如你学会了用户接口,你再去学其他的接口,它的使用方法和规范都是和用户接口相似的,你学起来肯定会简单。同时它也提升了可见性,因为所有的接口都遵循同一套规范,所以它们之间就会变得更加相似,更加透明。
那么接口有什么作用?
前后端可以通过接口来通信,前端只需要调用接口就可以了,不需要再实现具体的代码。比如过去我们想实现一个从 PDF 转为 word 这样一个功能,你就必须把这些代码写在前端,写在那些 windows 软件或者是麦凯这种软件上面。但是现在我们只需要调用一个接口就可以实现了。我们的接口实现其实就是一种解耦,这样一来,前后端就可以独立开发和迭代,两者之间只需要遵循同一套接口规范就可以了,谁也不用依赖谁,谁也不用去等谁。比如如果你在一个团队里面,前端说后端接口没写完,我根本就没法用,你可以告诉后端你要的是什么样一个接口,它就给你响应这样的一个数据就可以了。接口让你前后端可以独立开发和迭代的,让你们之间可以实现一个解耦。如果后端没有把接口给具体实现,它可以给你一些假数据,只要遵循接口规范,你就可以用。这就是接口的一个作用。
限制五:“分层系统”
第五个限制是分层系统。这个限制的意思是软件架构分了很多层,而且每一层只知道相连的那一层,后面的东西它是不知道的。比如客户端不知道自己是和代理通信,还是在和真实的服务器通信,客户端只知道自己最相邻的那一层,也就是接口。在这里代理其实就算是分层系统中的一层了。很多同学可能不太理解代理,我们来解释一下。比如你想翻墙去看一些国外的网站,或者你在家里面想连接公司的内网来办公,这时候你就需要用到代理了。看起来你好像访问的是谷歌或者是Facebook,但是其实你已经从代理那一层绕了一圈,才看到真正的服务器。
分层系统远不止代理这么简单。比如在阿里巴巴企业里面有一个部门叫中间件儿,这个部门儿就是用来开发中间件儿的。部门儿的开发人员其实是不用关心业务逻辑的,只需要去做一些中间件就可以了。这些中间件其实就是分层系统中的一些层,他们具体做了哪些层,比如有安全层
,负载均衡层
或者是缓存层
等等相关的。所谓的安全层,就是提供了终止掉一切错误的请求或者是不安全的请求,后面我会在出一篇文章详细讲讲错误处理,专门来写安全层的代码的。
负载均衡
另外还有一个层叫负载均衡。所谓的负载均衡就是你的软件或者你的网站用户量特别大的时候,请求也特别多的时候,比如双十一会有很多的请求,你就会用到很多服务器,它们之间共同分担这些流量。负载均衡这一层其实就是用来管理这些流量的分发的。比如这台服务器吃紧了,快撑不住了,要挂掉了怎么办?负载均衡这一层就负责把流量转到下台服务器,这就是负载均衡这一层的作用。
缓存层
还有一个层叫缓存层,这个缓存层主要是用于缓存一些静态文件。这一层其实也是比较简单的,我们在前面也已经提到过了。在现实项目中我们会编写大量的一个中间件,这种分层系统里面的层,我们会以中间件的形式来进行体现。
限制六:“按需代码”
最后一个限制按需代码。这个限制是可选的,它也不是特别重要,但是因为它是六大限制之一,所以我们为了一个完整性先提到它。所谓的按需代码,其实就是客户端可以下载运行服务端传来的代码,比如你可以让服务端给你传一段JS的字符串,在浏览器里面去执行。大家都知道在浏览器里面是如何执行JS的方法,其实有一个函数叫 eval 函数,就是 eval 这个函数如果还不知道,大家可以去搜一下按需代码有什么好处,它可以减少一些功能,简化客户端。也就是有些业务逻辑,前端不需要自己写,交给服务端就好了。服务端传给你一段代码,由前端来负责执行这段代码。所以它简化了客户端,提升了客户端的一个简单性。
到此, rest 简介我们就讲完了。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!