Skip to content

Latest commit

 

History

History
140 lines (77 loc) · 9.59 KB

1Api接口及设计规范.md

File metadata and controls

140 lines (77 loc) · 9.59 KB

Api接口及设计规范

!> 本篇着重介绍的为 RESTful 规范

应用程序编程接口(Application Programming Interface,API接口),就是应用程序对外提供了一个操作数据的入口,这个入口可以是一个函数或类方法,也可以是一个url地址或者一个网络地址。当客户端调用这个入口,应用程序则会执行对应代码操作,给客户端完成相对应的功能。

当然,api接口在工作中是比较常见的开发内容,有时候,我们会调用其他人编写的api接口,有时候,我们也需要提供api接口给其他人操作。由此就会带来一个问题,api接口往往都是一个函数、类方法、或者url或其他网络地址,不断是哪一种,当api接口编写过程中,我们都要考虑一个问题就是这个接口应该怎么编写?接口怎么写的更加容易维护和清晰,这就需要大家在调用或者编写api接口的时候要有一个明确的编写规范!!!

为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们都需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少客户端和服务端双方之间的合作成本。

目前市面上大部分公司开发人员使用的接口实现规范主要有:RESTfulRPC

RPC( Remote Procedure Call ): 翻译成中文:远程过程调用[远程服务调用]. 从字面上理解就是访问/调用远程服务端提供的api接口。这种接口一般以服务或者过程式代码提供。

  • 服务端提供一个唯一的访问入口地址http://api.xxx.com/http://www.xx.com/api 或者基于其他协议的地址

  • 客户端请求服务端的时候,所有的操作都理解为动作(action),一般web开发时,对应的就是HTTP请求的post请求

  • 通过请求体参数,指定要调用的接口名称和接口所需的参数

    action=get_all_student&class=301&sex=1

    m=get_all_student&sex=1&age=22

    command=100&sex=1&age=22

rpc接口多了,对应函数名和参数就多了,前端在请求api接口时难找.对于年代久远的rpc服务端的代码也容易出现重复的接口

1、RESTful API规范

REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移。 它首次出现在2000年Roy Fielding的博士论文中。

RESTful是一种专门为Web 开发而定义API接口的设计风格,尤其适用于前后端分离的应用模式中。

这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。

2、REST的指导原则(架构约束)

客户端 - 服务器 - 通过将用户接口问题与数据存储问题分开,我们通过简化服务器组件来提高跨多个平台的用户接口的可移植性并提高可伸缩性。

无状态 - 从客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上任何存储的上下文。因此,会话状态完全保留在客户端上。

可缓存 - 缓存约束要求将对请求的响应中的数据隐式或显式标记为可缓存或不可缓存。如果响应是可缓存的,则客户端缓存有权重用该响应数据以用于以后的等效请求。

统一接口 - 通过将通用性的软件工程原理应用于组件接口,简化了整个系统架构,提高了交互的可见性。为了获得统一的接口,需要多个架构约束来指导组件的行为。REST由四个接口约束定义:资源识别; 通过陈述来处理资源; 自我描述性的信息; 并且,超媒体作为应用程序状态的引擎。

分层系统 - 分层系统风格允许通过约束组件行为来使体系结构由分层层组成,这样每个组件都不能“看到”超出与它们交互的直接层。

按需编码(可选) - REST允许通过以小程序或脚本的形式下载和执行代码来扩展客户端功能。这通过减少预先实现所需的功能数量来简化客户端。

3、资源

REST中信息的关键抽象是一种资源。可以命名的任何信息可以是资源:文档或图像,临时服务,其他资源的集合,非虚拟对象(例如,人)等。REST使用资源标识符来标识组件之间交互中涉及的特定资源。

restful中要求,我们把当前接口对外提供哪种资源进行操作,就把资源的名称写在url地址

任何特定时间戳的资源状态称为资源表示。表示由数据,描述数据的元数据和超媒体链接组成,这些链接可以帮助客户转换到下一个期望的状态。

表示的数据格式称为**媒体类型**。媒体类型标识定义如何处理表示的规范。真正的RESTful API看起来像*超文本*。每个可寻址信息单元明确地(例如,链接和id属性)或隐式地(例如,从媒体类型定义和表示结构导出)携带地址。

此外,资源表示应该是自描述的:客户端不需要知道资源是员工还是设备。它应该基于与资源相关的媒体类型。因此在实践中,您最终将创建大量自定义媒体类型 - 通常是与一种资源相关联的一种媒体类型。

每种媒体类型都定义了默认处理模型。例如,HTML定义了超文本的呈现过程以及每个元素周围的浏览器行为。它与资源方法GET / PUT / POST / DELETE / ...没有任何关系,除了一些媒体类型元素将定义一个过程模型,其类似于“具有href属性的锚元素创建一个超文本链接,当被选中时,在与CDATA编码的href属性对应的URI上调用检索请求(GET)。“

4、资源方法

与REST相关的其他重要事项是用于执行所需转换的资源方法。许多人错误地将资源方法与HTTP GET / PUT / POST / DELETE方法联系起来。

Roy Fielding从未提及任何关于在哪种情况下使用哪种方法的建议。他所强调的是它应该是统一的接口。如果你决定HTTP POST将用于更新资源 - 而不是大多数人推荐HTTP PUT - 它没关系,应用程序接口将是RESTful。

不过大多数情况下人们已经认定使用HTTP的请求方法

web开发中操作资源,最常见的最通用的无非就是增删查改,所以restful要求在地址栏中声明要操作的资源是什么。然后通过http请求动词来说明对该资源进行哪一种操作.

POST http://www.xxx.com/api/students/ 添加学生数据

GET http://www.xxx.com/api/students/ 获取所有学生

GET http://www.xxx.com/api/students// 获取id=pk的学生

DELETE http://www.xxx.com/api/students// 删除id=pk的一个学生

PUT http://www.xxx.com/api/students// 修改一个学生的全部信息 [id,name,sex,age,]

PATCH http://www.xxx.com/api/students// 修改一个学生的部分信息[age]

对于数据资源分别使用POST、DELETE、GET、UPDATE等请求动作来表达对数据的增删查改。

请求方法 请求地址 后端操作
GET /students 获取所有学生
POST /students 增加学生
GET /students/ 获取编号为pk的学生
PUT /students/ 修改编号为pk的学生
DELETE /students/ 删除编号为pk的学生

也就是说,我们仅需要通过url地址上的资源名称结合HTTP请求动作,就可以说明当前api接口的功能是什么了。

restful是以资源为主的api接口规范,体现在地址上就是资源就是以名词表达。

rpc则以动作为主的api接口规范,体现在接口名称上往往附带操作数据的动作。

restful规范是一种通用的规范,不限制语言和开发框架的使用。事实上,我们可以使用任何一门语言,任何一个框架都可以实现符合restful规范的API接口。

参考文档:http://www.runoob.com/w3cnote/restful-architecture.html

5、幂等性

接口实现过程中,会存在幂等性。所谓幂等性是指代客户端发起多次同样请求时,是否对于服务端里面的资源产生不同结果。如果多次请求,服务端结果还是一样,则属于幂等接口,如果多次请求,服务端产生结果是不一样的,则属于非幂等接口。

请求方式 是否幂等 是否安全
GET 幂等 安全
POST 不幂等 不安全
PUT/PATCH 幂等 不安全
DELETE 幂等 不安全

6、序列化

api接口开发,最核心最常见的一个代码编写过程就是序列化,所谓序列化就是把数据转换格式。常见的序列化方式:

json,pickle,base64,struct,….

序列化可以分两个阶段:

序列化: 把我们识别的数据转换成指定的格式提供给别人。

例如:我们在django中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。

反序列化:把别人提供的数据转换/还原成我们需要的格式。

例如:前端js提供过来的json数据,对于python而言json就是字符串,我们需要进行反序列化换成字典,然后接着字典再进行转换成模型对象,这样我们才能把数据保存到数据库中。