【开发指南】RESTful接口设计

540 阅读5分钟

幂等性

1. 定义

幂等性是系统服务对外一种承诺(而不是实现)。承诺只要调用接口成功,外部多次调用对系统的影响是一致的。声明为幂等的服务会认为外部调用失败是常态,并且失败之后必然会有重试。

幂等不仅仅只是一次(或多次)请求对资源没有副作用(比如查询数据库操作没有对数据库有任何影响)。幂等还包括第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。简单来说就是多次访问REST服务产生的结果不会有改变。

2. 案例

以SQL为例,有下面三种场景,只有第三种场景需要开发人员使用其他策略保证幂等性:

1SELECT col1 FROM tab1 WHERE col2 = 2; 无论执行多少次都不会改变状态,是天然的幂等。

2UPDATE tab1 SET col1 = 1 WHERE col2 = 2; 无论执行成功多少次状态都是一致的,因此也是幂等操作。

3UPDATE tab1 SET col1 = col1 + 1 WHERE col2 = 2; 每次执行的结果都会发生变化,这种不是幂等的。

3. HTTP中的幂等性

HTTP协议明确规定,PUTGETDELETE请求都是具有幂等性的,而POST为非幂等性请求。就是说接口被定义为POST请求可访问时,说明这个接口对数据库的影响是非幂等性的。所以一般插入新数据时,用POST方法。更新数据时,用PUT方法。查询数据时,用GET方法。删除数据时,用DELETE方法。

4. 幂等性和安全性

  • 安全性:不会改变资源状态,可以理解为只读的;

  • 幂等性:执行1次和执行N次,对资源状态改变的效果是等价的。

20210320135855.png

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膨胀,不易维护。

单个资源和资源集合

  1. 单个资源

    /zoos/1  //id为1的动物园
    /zoos/1;2;3  //id为1,2,3的动物园
    
  2. 资源集合

    /zoos  //所有动物园
    /zoos/1/animals  //id为1的动物园中的所有动物
    

案例

  1. GET:查询

    GET /zoos:列出所有动物园
    GET /zoos/ID:获取某个指定动物园的信息
    GET /zoos/ID/animals:列出某个指定动物园的所有动物
    
  2. POST:创建单个资源。POST一般向"资源集合"型URI发起

    POST /zoos:新建一个动物园
    
  3. PUT:全量更新单个资源,客户端提供完整的更新后的资源

    PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
    
  4. PATCH:部分更新单个资源,客户端提供要更新的那些字段

    PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
    
  5. 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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。