幂等性
1. 定义
幂等性是系统服务对外一种承诺(而不是实现)。承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。
幂等不仅仅只是一次(或多次)请求对资源没有副作用(比如查询数据库操作没有对数据库有任何影响)。幂等还包括第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。简单来说就是多次访问REST
服务产生的结果不会有改变。
2. 案例
以SQL为例,有下面三种场景,只有第三种场景需要开发人员使用其他策略保证幂等性:
1、SELECT col1 FROM tab1 WHERE col2 = 2; 无论执行多少次都不会改变状态,是天然的幂等。
2、UPDATE tab1 SET col1 = 1 WHERE col2 = 2; 无论执行成功多少次状态都是一致的,因此也是幂等操作。
3、UPDATE tab1 SET col1 = col1 + 1 WHERE col2 = 2; 每次执行的结果都会发生变化,这种不是幂等的。
3. HTTP中的幂等性
HTTP
协议明确规定,PUT
、GET
与DELETE
请求都是具有幂等性的,而POST
为非幂等性请求。就是说接口被定义为POST
请求可访问时,说明这个接口对数据库的影响是非幂等性的。所以一般插入新数据时,用POST
方法。更新数据时,用PUT
方法。查询数据时,用GET
方法。删除数据时,用DELETE
方法。
4. 幂等性和安全性
-
安全性:不会改变资源状态,可以理解为只读的;
-
幂等性:执行1次和执行N次,对资源状态改变的效果是等价的。
RESTful接口设计标准
1. 定义
REST(Representational State Transfer)表述性状态转换,REST
指的是一组架构约束条件和原则。 如果一个架构符合REST
的约束条件和原则,我们就称它为RESTful
架构。REST
本身并没有创造新的技术、组件或服务,而隐藏在RESTful
背后的理念就是使用Web
的现有特征和能力, 更好地使用现有Web
标准中的一些准则和约束。虽然REST
本身受Web
技术的影响很深, 但是理论上REST
架构风格并不是绑定在HTTP
上,只不过目前HTTP
是唯一与REST
相关的实例。
2. 协议方法选择
Spring4.3
中引进了@GetMapping
、@PostMapping
、@PutMapping
、@DeleteMapping
、@PatchMapping
来帮助简化常用的HTTP
方法的映射,并更好地表达被注解方法的语义。
@GetMapping
对应注解:@RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)
作用:对应查询,获得数据,表明是一个查询请求。
@PostMapping
对应注解:@RequestMapping(value = “/add/user”,method = RequestMethod.POST)
作用:对应添加,添加数据,表明是一个添加请求。
@PutMapping
对应注解:@RequestMapping(value = “/modify/user”,method = RequestMethod.PUT)
作用:对应更新,更新数据,表明是一个更新请求。
@DeleteMapping
对应注解:@RequestMapping(value = “/delete/{id}”,method = RequestMethod.DELETE)
作用:对应删除,删除数据,表明是一个删除请求。
@PatchMapping
@PatchMapping是对PUT
方式的一种补充。PUT
更侧重于对整体的更新,PATCH
是对局部的更新。
3. URI设计
URI
URI 表示资源,资源一般对应服务器端领域模型中的实体类。
URL设计规范
- 全部为小写字母。
- 用中划线 "-" 不用下划线 "_" 。
- 名词表示资源集合,使用复数形式。
- 避免过深的URI,过深容易导致URI膨胀,不易维护。
单个资源和资源集合
-
单个资源
/zoos/1 //id为1的动物园 /zoos/1;2;3 //id为1,2,3的动物园
-
资源集合
/zoos //所有动物园 /zoos/1/animals //id为1的动物园中的所有动物
案例
-
GET:查询
GET /zoos:列出所有动物园 GET /zoos/ID:获取某个指定动物园的信息 GET /zoos/ID/animals:列出某个指定动物园的所有动物
-
POST:创建单个资源。POST一般向"资源集合"型URI发起
POST /zoos:新建一个动物园
-
PUT:全量更新单个资源,客户端提供完整的更新后的资源
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
-
PATCH:部分更新单个资源,客户端提供要更新的那些字段
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
-
DELETE:删除
DELETE /zoos/ID:删除某个动物园 DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物
4. 响应数据设计
- GET /collection:返回资源对象的列表(数组)
- GET /collection/resource:返回单个资源对象
- POST /collection:返回新生成的资源对象
- PUT /collection/resource:返回完整的资源对象
- PATCH /collection/resource:返回完整的资源对象
- DELETE /collection/resource:返回一个空文档
5. 状态码
- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
- 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
- 204 NO CONTENT - [DELETE]:用户删除数据成功。
- 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
- 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
- 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
- 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
- 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
- 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
- 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
- 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。