Resful-API接口规范
REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移,简单来讲就是"资源状态转移"。
RESTful是一种设计风格,用于构建可伸缩的网络应用程序,其基本原则是使用标准的HTTP请求方法来操作资源,并使用统一的资源标识符(Uniform Resource Identifiers,URI)来表示资源。
1. RESTful规范介绍:
-
资源:
在REST中,每个实体被视为一个资源。资源可以是任何东西,如用户、产品、文章等。
-
URI:
每个资源通过唯一的URI进行标识,URI用于定位资源
eg: 例如:http://api.study.com/users/123 就代表用户ID=123的用户接口
-
HTTP方法:
RESTful API使用HTTP方法来定义对资源的操作。常用的HTTP方法包括GET、POST、PUT、DELETE等。
常用的HTTP方法对应于RESTful接口中的应用如下:
(1)GET:从服务器获取资源或资源的属性。
(2)POST:在服务器上创建新资源。
(3)PUT:在服务器上更新现有资源或替换资源。(一般用于更新所有信息)
(4)PATCH:部分更新服务器上的资源,(只修改资源的一部分属性)
(5)DELETE:从服务器删除资源。
2. 不同HTTP请求案例详解
2.1 GET 请求
GET请求方法示例:
- 描述:用于从服务器获取资源或其属性的信息。
- 示例:获取单个用户信息
如下是GET请求获取所有用户信息
GET https://api.example.com/users/ # 获取所有学生信息
在RESTful中,获取指定标识的资源通常使用HTTP的GET方法,并在URI中包含标识符来唯一标识该资源。
# 请求格式
GET https://api.example.com/users/<pk> # 唯一标识
GET https://api.example.com/users/66 # 获取id=66的用户信息
2.2 POST 请求
POST请求方法示例:
- 描述:用于在服务器上创建新资源。
- 示例:创建新用户
POST https://api.example.com/users # 创建用户接口
Body:
{
"name": "老八",
"email": "laoba@example.com",
"money": 888888,
}
# POST接口的请求体,用于传输创建信息
2.3 PUT 请求
- 描述:用于更新服务器上现有资源的属性或替换资源。
- 重点: 一般用于更新所有信息,PATCH请求更新部分信息
- 示例:更新用户全部信息
PUT https://api.example.com/users/123 # 更新用户id=123的全部信息
Body:
{
"name": "Jane Smith",
"email": "jane.smith@example.com"
}
# 请求体与POST接口类似
2.4 PATCH 请求
- 描述:用于部分更新资源,只更新资源的部分属性。
- 重点: 一般用于
- 示例:更新用户的部分信息
PATCH https://api.example.com/users/50/name/老六 # 将id=50的用户的name->老六
Body:
{
"email": "new.email@example.com" # 在这里,只更新了邮箱,并没有更新name
}
2.5 DELETE 请求
- 描述:用于删除服务器上的资源。
- 示例:删除用户
DELETE https://api.example.com/users/123 # 删除用户id=123的用户
RESTful设计风格强调使用HTTP方法来表示对资源的操作,同时也要求URI应该是有意义的和自描述的。使用RESTful规范可以使API更加清晰、易于理解和维护,并且能够更好地利用HTTP协议的特性。
3. 幂等性(面试常考)
3.1 幂等性介绍
幂等性是RESTful API中的一个重要概念和特性。
幂等性是指对同一个资源的多次请求所产生的影响与一次请求的影响相同,即无论对同一资源发起多少次请求,最终的结果都是一致的。这意味着在客户端发起一次请求失败后,可以尝试重新发送相同的请求,而不会导致错误结果或数据重复。
在RESTful API设计中,特别是涉及对资源进行修改的请求(例如POST、PUT、DELETE等),要尽量保持幂等性。这样可以避免客户端因为网络问题或其他原因而重试请求,导致资源状态发生不一致或不确定的情况。
幂等性的实现要求请求的副作用相同,即对资源的状态修改在多次请求时产生的效果一致。一些常见的实现幂等性的方式包括:
- 使用唯一标识符:对于每个资源,可以使用唯一的标识符来区分不同的请求,确保重复的请求不会对同一资源进行重复操作。
- 乐观并发控制:通过在请求中包含版本号或时间戳等信息,服务器可以检查请求的合法性,避免多个并发请求造成资源冲突或数据不一致。
- 幂等性标记:某些情况下,服务器可以为每个请求生成一个唯一的幂等性标记,并在请求中使用该标记,以确保相同标记的请求只会被处理一次,重复请求会被忽略。
- 合适的HTTP方法:在设计API时,选择合适的HTTP方法也能帮助实现幂等性。例如,使用PUT方法来更新资源,使用DELETE方法来删除资源,这些方法本身就应该是幂等的。
3.2 幂等性案例详解
假设我们有一个简单的RESTful API,用于管理用户资源,其中包含一个更新用户信息的接口。我们将使用HTTP的PUT方法来更新用户信息,同时确保该接口具有幂等性。
设计幂等性接口的关键在于**保证接口不论是被调用1次还是N次,它对资源所产生的影响都是相同的
**
现在,如果客户端出现网络问题或其他原因未能收到服务器的响应,于是重新发送同样的请求。
例如用户购买商品,用户提交支付以后,服务器卡顿,结果连续提交了很多次支付
那么如果服务器后面收到了,按正常的处理逻辑,服务器会进行连续几次的业务逻辑,导致用户重复下单,在实际业务处理中,往往会通过资源标识符的方法,对请求进行标识
实现商品订单的支付
- HTTP方法:POST
- 资源URI:
https://api.example.com/pays/
- 请求体:
{
"ordId":666666, # 唯一标识符,ordId
"money":500
}
支付系统需要对这个支付订单号做交易的幂等。
- 如果不存在该支付订单号,则记库,并标记状态为支付中,然后调用渠道进行支付落地。
- 收到渠道异步通知或者通过查询得到渠道支付状态时,更新该笔支付订单状态
- 如果客户再次发起支付,不给客户产生新的支付订单号,先用该笔支付订单号调用支付系统,支付系统会判断订单号幂等性,如果已支付,则报错告诉客户已支付成功,请勿重复支付;如果支付失败,则新产生流水调用渠道进行支付落地;如果支付状态未知,则告诉客户,交易状态未知,请发起查询或者关单。
- 针对状态未知这种情况,如果支持冲正和关单则最好,如果不行,只能让客户发起查询。在这种情况下,如果客户等不及,才流转到最坏的可能,客户重新下一单商品订单,这单根据最终渠道对账情况,给客户做退款。这种情况下需提示客户确认未发起前一笔支付,再新创建,否则,前一笔需要等第二个工作日状态确认后进行退款处理。
3.3 其他HTTP请求解释
method description
GET 请求指定页面信息,并返回实体主体
HEAD 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT 从客户端向服务器传送的数据取代指定的文档的内容。(全部取代)
PATCH 从客户端向服务器传送的数据取代指定的文档的内容。(部分取代)
DELETE 请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE 回显服务器收到的请求,主要用于测试或诊断。
method | description | 是否幂等 |
---|---|---|
GET | 请求指定页面信息,并返回实体主体 | 是 |
HEAD | 类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头 | 是 |
POST | 用于在服务器上创建新资源,所以存在重复创建风险,不符合幂等 | 否 |
PUT | 更新指定数据的全部数据 | 是 |
PATCH | 更新指定数据的部分数据 | 否 |
DELETE | 删除指定数据 | 是 |
CONNECT | HTTP/1.1 协议中预留,将连接改为代理服务器。 | 是 |
OPTIONS | 允许客户端查看服务器的性能。(在浏览器发起POST/GET时一般会自动调用) | 是 |
TRACE | 回显服务器收到的请求,主要用于测试或诊断。 | 是 |
3.4 为什么PUT时幂等的,PATCH却不是幂等
PUT和PATCH明明都是修改资源,但是幂等性却是相反,这需要我们深度追溯两种请求方式的区别。
-
PUT请求(修改指定资源的全部数据)
对于PUT,其实在后端逻辑中,就是直接替换资源,例如name:“张三”,money:50,直接替换成小明,80,所以就算进行多少次的请求,都不会影响替换成小明80的结果,所以他是幂等的。
-
PATCH请求(修改指定资源的部分数据)
PATCH请求,我们对于金额的修改,例如money:50,我们在进行请求时往往是实现对"money"的增加以及减少,例如实现加30以及减30,如果进行多次的请求,则会导致数据多次被增加,就会导致数据出问题。
4. RESTfulAPI版本管理
在实际项目中,我们可能会随着需求变化,API接口也需要进行变化,但是又不能把旧项目中的处理逻辑全部更改,所以就需要有接口的版本控制。
4.1 通过URL Path区分版本
版本V1与V2
https://api.example.com/v1/users/123 #V1
-----------------------------------
https://api.example.com/v2/users/123 # V2
4.2 通过请求参数进行版本控制
https://api.example.com/v1/users/param?version=1 # 版本1
-----------------------------------
https://api.example.com/v2/users/param?version=2 # 版本2
4.3 通过自定义请求头进行版本控制
# 例如在请求头中定义API版本参数
X-API-VERSION:2 # 版本2
X-API-VERSION:1 # 版本1