概念
REST原则提倡按照HTTP的语义使用HTTP,如果一个系统符合REST原则,我们就说这个系统是Restful风格的。Restful是Web API设计中非常重要的一个概念,但是很多开发人员对于Restful的理解存在误区。
什么是Restful
在说什么是Restful 之前,我们首先要知道在Web API开发中有两种风格,一种是面向过程的(简称RPC)还有一种面向REST的(简称REST),在知道有这两风格后我们通对比的方式能更好的理解什么Restful。
在RPC风格的Web API中,我们通过“控制器/操作方法”的形式来调用服务器端的方法,把服务器端的代码当成方法去调用。这种风格的接口可能会用POST请求处理所有的操作方法,无论是获取、新增、更新还是删除数据,这样的接口只是把HTTP当成一个传输数据的通道,而不关心HTTP谓词的语义。在这样的接口中,我们通过QueryString(查询字符串)或者请求报文体来为服务器传递数据。只要服务器端能够正常完成客户端请求的处理,服务器就会统一返回200的HTTP状态码。对于逻辑上的错误,返回的HTTP状态码也是200,只不过在响应报文体中通过不同的错误码来表示,比如 {"code":1,"msg":"用户不存在"}。
与之对应,在REST风格的Web API中,接口把服务器端当成资源来处理。REST风格的接口按照HTTP设计之初的语义来使用HTTP,把系统中的所有内容都抽象为资源,所有对资源的操作都是无状态的且可以通过标准的HTTP谓词来进行。
举个例子可能更好理解这句话的含义,例如:我们有个根据用户id查看用户详细的接口,按照RPC 风格设计的话,大概是这样:api/User/GetUserById?id=1,Restulf风格:api/user/1,对比这两个路由很容易就能看出,Restulf风格把查询用户id为1的请求参数当作了路由的一部分,可以理解为资源。
Restful设计规范
(1)所有的资源都尽量通过URL来表示,避免通过QueryString、报文体来对资源进行定位,这样URL的语义性更清晰。
(2)对所有类型资源的新增、删除、修改、查询操作都统一为向资源发送POST、DELETE、PUT、GET请求,接口统一且具有自描述性,减少了开发人员对接口文档的依赖性。
(3)对于GET、PUT、DELETE等幂等的操作,网关、网络请求组件等可以对失败的请求自动重试。
(4)网关等可以对GET请求进行缓存,能够提升系统的访问速度,而且降低服务器的压力。
(5)通过HTTP状态码反映服务器端的处理结果,能够统一错误码,避免自定义错误码带来的不统一的问题。客户端也可以根据错误码进行统一处理,比如对于403状态码,客户端统一提示用户去登录。
如果严格按照上面的Restful设计范来设计我们API会存在如下问题:
(1)真实系统中的资源非常复杂,很难清晰地进行资源的划分,因此Restful风格对设计人员的IT技能和业务知识的水平要求都非常高。
(2)真实系统中的业务很复杂,并不是所有的操作都能简单地对应到PUT、GET、DELETE、POST上。而且对于同一个资源的同一个HTTP谓词有时候有多个业务逻辑,例如:api/user/DeleteById?id=1、api/user/DeleteByAccount?account=adm001 这两个都删除用户的的接口,一个是根据用户id,一个是根据用户账号(account)删除。
(3)在Restful中,资源尽量通过URL来定位,要尽量避免使用QueryString及请求报文体传递数据。例如:api/user/1、api/user/1/age/18,像这种地址并不符合中文的表达习惯,因此这样写会让很多开发人员迷惑。
(4)HTTP状态码的个数是有限的,特别是用于表示业务相关的错误码主要在4xx状态码段中,而业务系统中的错误非常复杂,仅通过HTTP状态码来反映错误有时候会无法满足要求。
(5)有一些宽带运营商、路由器、浏览器会对非200状态码的响应报文进行篡改。比如,把状态码为404的响应报文篡改为了广告内容。
(6)有的客户端是不支持PUT、DELETE请求的,比如旧版本的支付宝小程序、一些旧版浏览器等就不支持PUT、DELETE请求。
两种风格的对比图:
结论
我们知道REST是比较学术化的概念,它只是一个参考的风格,并不一定需要严格遵守Restful风格。AWS、ElasticSearch等的接口比较接近于Restful风格,因为这些系统的业务资源比较固定、业务流程变化不大而很多互联网系统、业务系统比这些系统复杂很多,而且面临的使用场景也更加复杂,因此即使是腾讯、阿里巴巴等大公司的业务相关接口,很多也不是完全遵守Restful风格的。
REST概念是用来指导我们设计接口的,而不是给开发带来麻烦的,不能因为要遵守Restful风格而影响开发进度及系统的稳定。如果项目的资源及业务流程像AWS、ElasticSearch等比较清晰、固定,并且开发团队中有对REST理解非常深入的开发人员,那么我们可以严格遵守Restful风格。但是对于大部分系统,业务资源和业务流程都是非常复杂的,业务需求的变动也是比较频繁的,而且大部分项目的开发人员的技术是参差不齐的,如果严格遵守Restful规范,会使得新员工的培养周期变长。因此在进行项目开发的时候,需要根据项目特点、公司人员等多方面情况,确定一个符合项目情况的定制版Restful规范。