什么是RESTful?RESTful详解

什么是RESTful

出处

2000 年 Roy Fielding 的博士论文中(论文地址见下方,感兴趣的可以看看),Roy Fielding是 HTTP 规范的主要编写者之一、Apache服务器软件的作者之一、Apache基金会的第一任主席。
Roy Fielding

论文REST章节地址:Fielding Dissertation: CHAPTER 5: Representational State Transfer (REST)

论文地址:Architectural Styles and the Design of Network-based Software Architectures

解释

REST是REpresentational State Transfer的简写(全称Resource Representational State Transfer),翻译过来就是“表现层状态转移”。这句话不是正常人能理解的,我也不理解。

引用一句我能理解的话来说就是:

URL定位资源,用HTTP动词(GET,POST,PUT,DELETE)描述操作。

注:引用自https://blog.csdn.net/hjc1984117/article/details/77334616

然后拆分下Resource Representational State Transfer这四个单词:

  • Resource:资源,即"数据";
  • Representational:某种表现形式--"资源"具体呈现出来的形式,比如用JSON,XML,JPEG等;
  • State Transfer:状态变化。通过HTTP动词实现(GET、POST、PUT、DELETE等)。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。

RESTful API就是REST风格的API,RESTful是一种软件架构风格,而不是标准。风格意思就是大家默认的但不是强制的。

RESTful 详解

URL 定位资源

REST 的主体是资源,所谓“资源”,即数据,就是网络上的一个具体信息,例如:一张图片,一段文字、一种服务。总之就是一个实际存在的东西,而 URL 就是用来指向这个资源的。

https://api.example.com/users

这个 URL 一看就知道是对 user 资源的操作。URL 中只使用名词来指定资源,不包含操作。为什么呢?

如果要包含操作,那至少有增删改查四种,那么上例中的一个接口至少要变成四个:

https://api.example.com/add_user
https://api.example.com/delete_user
https://api.example.com/update_use
https://api.example.com/get_user

如果可能还会有更多。

用 HTTP 动词描述操作

那怎么描述操作呢?答案就是用 HTTP 动词。

HTTP 动词,可能很多人第一眼看到的时候有点蒙,不知道是啥,其实就是我们请求网页时用的 GET、POST 等操作。我们平时用的最多的就是 GET 和 POST(例如写爬虫的时候,基本都是这两种),常用的还有 PUT、PATCH、DELETE 。

对资源的操作,无外乎 CRUD(增删改查),RESTful 中,每个 HTTP 动词对应一个 CRUD 操作。

  • GET:对应 Retrieve 操作(查询操作)
  • POST:对应 Create 操作
  • DELETE:对应 Delete 操作
  • PUT:对应 Update 操作
  • PATCH:对应 Update 操作

POST 和 PUT 的区别

一般说到 HTTP 动词对应 CRUD 的时候,PUT 都是对应 Update 操作的。但其实,PUT 也可以做 Create 操作。二者的区别在于:

  • URL:POST 不需要指定到个体,例如新增 user 的接口 POST /api/users。 PUT 的 URL 需要指定到具体的个体,例如 PUT /api/users/1,如果 1 这个 user 存在,则 Update,否则 Create。这个很好理解,POST 确定是新增,insert 的时候是不需要 where 条件的;PUT 则不行,update 的时候不加 where。另外,PUT 的时候,也不是每个 user 就要建一个接口的,这里需要用到的就是路由,一般是写成 PUT /api/users/{id},这样就具有一般性了。路由在这里就不展开讲了。
  • 幂等性:PUT 是幂等的,而 POST 是非幂等的。关于幂等性,见下文。

PATCH 和 PUT 的区别

PATCH 是 2010 后成为的正式 http 方法,它是对 PUT 的补充。在没有 PATCH 之前,都是用 PUT 进行更新操作,这时候我们的接口中通常会有一个逻辑规则,如:如果对象的一个属性值为null,那么就不更新该属性(字段)值,通过这种方式来避免全部覆盖的操作。现在有了 PATCH 就解决了这种判断,在 PUT 操作中不管属性是不是 null,都进行更新,在 PATCH 接口中就对非 null 的进行更新。另外,PATCH 是非幂等的。

变通的 POST

按照 REST 建议,查询操作要使用 GET 方法,但是实际情况中处理起来比较麻烦,如:报表统计查询,需要传递的参数很多,如果采用 GET 方法,那么接口接收的参数非常多,接口很难看,通常会封装为 java 对象,但 GET 方法又不支持对象传参,所以很蛋疼。

对于这种情况,最简单的方式就是改成 POST 方式,而且很多公司都是这么干的。可见 REST 只是建议,并非强制约束。

幂等性

幂等(Idempotence)本来是一个数学上的概念,后来拓展到计算机领域,描述为:

一个操作、方法或者服务,其任意多次执行所产生的影响均与一次执行的影响相同。

一个幂等的方法,使用同样的参数,对它进行多次调用和一次调用,对系统产生的影响是一样的。所以,对于幂等的方法,不用担心重复执行会对系统造成任何改变。

举个例子,用户 X 的手机话费余额为 2 元,他用支付宝给手机充了 100 元话费,如果将这个操作描述为“给 X 的账户余额增加 100 元”那就是非幂等的,重复操作几次运营商就亏大了。但是,如果将这个操作描述为“将 X 的账户余额设置为 102 元”,那这个操作就是幂等的。简单来说:

  • 幂等操作:将账户 X 的余额设置为 102 元;
  • 非幂等操作:将账户 X 的余额增加 100 元。

注意:这里的幂等性的例子并不严谨,本文主要不是讲幂等性的,所以只是举个简单的例子,不做深入探讨。

RESTful 的其他细节

命名规则

  • 全部小写,用 _ 或 - 线连接。(之所以不用驼峰命名法,是因为早期的 URI 一般都是表示服务器上的文件路径,而不同服务器对大小写的敏感性是不同的,为了兼容不同服务器所以才规定不能混用大小写字母。)
  • URL 中只用名词指定资源,因为 REST 的核心是资源,而表示资源的词语天然就是名词。
  • 资源用复数表示。

版本

一种方法是在 URL 中添加版本号,例如:

https://api.example.com/v1/users

另一种方法是将版本号加在 HTTP 请求头信息的 Accept 字段中,例如:

Accept: version=1.0

网上能找到的版本号加在 URL 中的例子,都是如我上例所示的写法。但是 Jack_Zeng 指出,这样写容易有歧义,会让人误以为 v1 也是资源的一部分,一般都是这么写:

https://api.example.com/users?api-version=1

常用 HTTP 状态码

http 状态码有 100 多种,我们并不需要全部用到,只需要了解其中常用的就可以了。

  • 200 – OK – 一切正常
  • 201 – OK – 新资源已经被创建
  • 204 – OK – 资源删除成功
  • 304 – 没有变化,客户端可以使用缓存数据
  • 400 – Bad Request – 调用不合法,确切的错误应该在 error payload 中描述
  • 401 – 未认证,调用需要用户通过认证
  • 403 – 不允许的,服务端正常解析和请求,但是调用被回绝或者不被允许
  • 404 – 未找到,指定的资源不存在
  • 422 – 不可指定的请求体:只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失
  • 500 – Internal Server Error:标准服务端错误,开发人员应该尽量避开这种错误

使用标准的http状态码可以让人看到 http status code 就知道结果如何。

当然这也只是RESTful风格的一种体现,而不是标准。


除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/archives/article/1106

分享到:
打赏 赞(0)
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

   

说点什么

avatar
  订阅  
提醒