当前位置: 首页 > news >正文

RESTful API设计指南:构建高效、可扩展和易用的API

文章目录

  • 引言
  • 一、RESTful API概述
    • 1.1 什么是RESTful API
    • 1.2 RESTful API的重要性
  • 二、RESTful API的基本原则
    • 2.1 资源导向设计
    • 2.2 HTTP方法的正确使用
  • 三、URL设计
    • 3.1 使用名词而非动词
    • 3.2 使用复数形式表示资源集合
  • 四、请求和响应设计
    • 4.1 HTTP状态码
    • 4.2 响应格式
      • 4.2.1 响应实体信息
      • 4.2.2 响应列表格式
      • 4.2.3 响应分页格式
    • 4.3 使用 HATEOAS 导航到相关资源
    • 4.4 错误处理
  • 五、URI 版本管理
    • 5.1 常见的版本控制策略
    • 5.2 如何选择
  • 六、数据筛选和分页
    • 6.1 分页和过滤
  • 总结

在这里插入图片描述

引言

在当今互联网时代,应用程序和服务之间的通信变得越来越重要。随着移动设备的普及、云计算的发展以及物联网的兴起,我们需要一种灵活、高效且易于理解的方式来设计和实现这些通信接口。RESTful API应运而生,成为了现代软件架构中不可或缺的一部分。

一、RESTful API概述

images (2)

1.1 什么是RESTful API

RESTful API(Representational State Transfer API),中文翻译过来可以表述为表述性状态转移,是一种基于HTTP协议的网络应用程序接口风格。它遵循REST架构风格的约束条件和原则,以资源为中心,使用标准的HTTP方法(如GET、POST、PUT、DELETE等)来执行操作。RESTful API强调简单性、可扩展性和可读性,使得不同系统之间的通信变得更加直观和高效。

1.2 RESTful API的重要性

RESTful API在现代软件开发中扮演着关键角色,其重要性体现在以下几个方面:

  1. 标准化:RESTful API遵循统一的设计原则,使得不同开发团队和系统之间的集成变得更加容易。
  2. 可扩展性:基于资源的设计使得API能够轻松地适应新的需求和功能扩展。
  3. 简单易用:RESTful API的设计理念使得接口更加直观,降低了开发者的学习成本。

本文旨在提供一个RESTful API设计指南,帮助开发人员构建高效、可扩展和易用的API。我们将介绍RESTful API设计的原则、最佳实践和模式,并提供一些实用的技巧和示例。通过遵循这些指南,开发人员可以设计出易于理解、易于使用和易于维护的API。

二、RESTful API的基本原则

2.1 资源导向设计

资源是RESTful API的核心概念。每个资源都应该有一个唯一的标识符(通常是URL)。设计API时,应该围绕资源而不是动作来组织。例如,一个用户资源可能表示为 /users/{id}

2.2 HTTP方法的正确使用

RESTful API利用HTTP方法来表示对资源的操作,常用的有下面几种:

  • GET(SELECT):获取资源
  • POST(CREATE):创建新资源
  • PUT(UPDATE):更新现有资源
  • DELETE(DELETE):删除资源
  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

范例:

GET 		/users  // 获取用户列表
POST 		/users  // 创建新用户
PUT 		/users/{userId} //获取指定ID的用户信息
PUT 		/users/{userId}  // 更新指定ID的用户信息
DELETE 		/users/{userId}  // 删除指定ID的用户
PATCH 		/users/{userId}  // 更新指定ID用户的部分信息

除此之外还有两种:

  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

三、URL设计

3.1 使用名词而非动词

URL应该表示资源,而不是动作。使用HTTP方法来表示动作。

范例:

  • GET /articles
  • POST /articles

避免:

  • GET /getArticles
  • POST /createArticle

3.2 使用复数形式表示资源集合

对于资源集合,使用复数形式更为直观。

范例:

  • GET /users
  • GET /users/{id}

避免:

  • GET /user
  • GET /user/{id}

四、请求和响应设计

4.1 HTTP状态码

HTTP状态码是表示请求结果的标准方式。正确使用状态码可以提高API的可读性和一致性。

HTTP状态码范围:

分类分类描述
1**信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3**重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
502 Bad Gateway - [*]:服务器作为网关或代理,从上游服务器收到无效响应。
503 Service Unavailable - [*]:服务器当前无法处理请求,可能是由于过载或维护。
504 Gateway Timeout - [*]:服务器作为网关或代理,没有及时从上游服务器收到响应。

根据具体情况选择适当的状态码,避免滥用200状态码来表示所有情况。

4.2 响应格式

请求响应传输数据格式:JSON,JSON数据尽量简单轻量,避免多级JSON的出现。

4.2.1 响应实体信息

{code: 200,msg: "success",data: {entity: {id: 1,name: "XXX",code: "XXX"}}
}

4.2.2 响应列表格式

{code: 200,msg: "success",data: {records: {entity: {id: 1,name: "XXX",code: "XXX"},entity: {id: 2,name: "XXX",code: "XXX"}}}
}

4.2.3 响应分页格式

{"msg": "success","code": 200,"data": {"current": 0,"records": [{id: 1,name: "XXX",code: "H001"},{id: 2,name: "XXX",code: "H001"}],"size": 5,"total": 2}
}

分析:

  • data: 数据主体,包含了分页信息和记录列表。
    • current: 当前页码,这里的值为 0,表示第一页(具体按照公司规范)。
    • records: 记录列表,包含了当前页的所有记录,每个记录包含 idnamecode 字段。
    • size: 每页大小,这里的值为 5,表示每页最多显示5条记录。
    • total: 总记录数,这里的值为 2,表示一共有2条记录。

4.3 使用 HATEOAS 导航到相关资源

REST 背后的主要动机之一是它应能够导航整个资源集,而无需事先了解 URI 方案。 每个 HTTP GET 请求应通过响应中包含的超链接返回查找与所请求的对象直接相关的资源所需的信息,还应为它提供描述其中每个资源提供的操作的信息。 此原则称为 HATEOAS 或作为应用程序状态引擎的超文本。

由于当前没有如何为 HATEOAS 原则建模的任何通用标准,因此此部分的示例仅作为一个可能的参考。

例如,若要处理订单与客户之间的关系,可以在订单的表示形式中包含链接,用于指定下单客户可以执行的操作。 下面是可能的表示形式:

{"orderID":3,"productID":2,"quantity":4,"orderValue":16.60,"links":[{"rel":"customer","href":"https://adventure-works.com/customers/3","action":"GET","types":["text/xml","application/json"]},{"rel":"customer","href":"https://adventure-works.com/customers/3","action":"PUT","types":["application/x-www-form-urlencoded"]},{"rel":"customer","href":"https://adventure-works.com/customers/3","action":"DELETE","types":[]},{"rel":"self","href":"https://adventure-works.com/orders/3","action":"GET","types":["text/xml","application/json"]}]
}

在此示例中,links 数组包含一组链接。 每个链接表示可对相关实体执行的操作。 每个链接的数据包含关系 (“customer”)、URI (https://adventure-works.com/customers/3)、HTTP 方法和支持的 MIME 类型。 这是客户端应用程序在调用操作时所需的全部信息。

links 数组还包含有关已检索的资源本身的自引用信息。 这些链接包含关系 self

4.4 错误处理

错误响应应包含:

  • HTTP状态码
  • 错误消息
  • 错误代码(可选)
  • 详细说明(可选)

例如:

{"code": "50x","message": "The provided email address is invalid"
}

五、URI 版本管理

5.1 常见的版本控制策略

  1. URI 路径版本控制
    例如:/api/v1/users
  2. 查询参数版本控制
    例如:/api/users?version=1
  3. 自定义 HTTP 头版本控制
    例如:Accept-version: v1
  4. Accept 头版本控制
    例如:Accept: application/vnd.myapp.v1+json

5.2 如何选择

选择版本控制策略时,还应考虑对性能的影响,尤其是在 Web 服务器上缓存时。 URI 路径版本控制和查询参数版本控制方案都是缓存友好的,
因为同一 URI/查询字符串组合每次都指向相同的数据。

自定义 HTTP 头版本控制和Accept 头版本控制机制通常需要其他逻辑来检查自定义标头或 Accept 标头中的值。 在大型环境中,使用不同版本的
Web API 的多个客户端可能会在服务器端缓存中生成大量重复数据。 如果客户端应用程序通过实现缓存的代理与 Web 服务器进行通信,并且该
代理在当前未在其缓存中保留所请求数据的副本时,仅将请求转发到 Web 服务器,则此问题可能会变得很严重。

六、数据筛选和分页

6.1 分页和过滤

对集合资源执行的 GET 请求可能返回大量的项。 应将 Web API 设计为限制任何单个请求返回的数据量。 请考虑支持查询字符串指定要检索的最大项数和集合中的起始偏移量。

  • 分页:

    • 使用 limit 和 offset 参数
    • 或者使用基于游标的分页
  • 过滤:

    • 允许客户端指定过滤条件
    • 使用查询参数进行过滤
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100&status=active:指定第几页,以及每页的记录数,相应数据的状态。
?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
?animal_type_id=1:指定筛选条件

总结

设计高质量的 RESTful API 是一个持续的过程。通过遵循本指南中的原则和最佳实践,你可以创建出高效、可扩展且易于使用的 API。记住,优秀的 API 设计不仅能提高开发效率,还能为你的产品或服务创造更大的价值。如要想要获取更多参考范例,可以参考Github的API接口,Github使用的就是RESTful API,希望本文对大家有所帮助😊。


参考文章:

RESTful Web API 设计

HTTP状态码

GitHub REST API 文档

RESTful API 设计指南——阮一峰

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 达梦数据库DM8-索引篇
  • 【GraphRAG】微软 graphrag 效果实测
  • Keysight 是德 DSA90804A 高性能示波器
  • 基于centos2009搭建openstack-t版-ovs网络-脚本运行
  • 数据库系统概论:数据库系统的锁机制
  • 「MQTT over QUIC」与「MQTT over TCP」与 「TCP 」通信测试报告
  • oracle 经营范围 设计
  • 学习大数据DAY20 Linux环境配置与Linux基本指令
  • 【java】力扣 合并两个有序数组
  • IDEA创建Java工程、Maven安装与建立工程、Web工程、Tomcat配置
  • 脑肿瘤有哪些分类? 哪些人会得脑肿瘤?
  • buu做题(5)
  • layui前端开发-记录一次弹窗嵌套表格功能的开发
  • 科研绘图系列:R语言circos图(circos plot)
  • C++那些事之依赖注入
  • (ckeditor+ckfinder用法)Jquery,js获取ckeditor值
  • [LeetCode] Wiggle Sort
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Golang-长连接-状态推送
  • IDEA 插件开发入门教程
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • react 代码优化(一) ——事件处理
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • tab.js分享及浏览器兼容性问题汇总
  • vue2.0项目引入element-ui
  • 大数据与云计算学习:数据分析(二)
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 诡异!React stopPropagation失灵
  • 两列自适应布局方案整理
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 前端性能优化——回流与重绘
  • 巧用 TypeScript (一)
  • 如何合理的规划jvm性能调优
  • 温故知新之javascript面向对象
  • 正则学习笔记
  • 智能合约开发环境搭建及Hello World合约
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​ubuntu下安装kvm虚拟机
  • ​低代码平台的核心价值与优势
  • # Redis 入门到精通(一)数据类型(4)
  • # windows 安装 mysql 显示 no packages found 解决方法
  • ### RabbitMQ五种工作模式:
  • #laravel 通过手动安装依赖PHPExcel#
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #每天一道面试题# 什么是MySQL的回表查询
  • (02)vite环境变量配置
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (2)Java 简介
  • (2024,RWKV-5/6,RNN,矩阵值注意力状态,数据依赖线性插值,LoRA,多语言分词器)Eagle 和 Finch
  • (33)STM32——485实验笔记
  • (八)Flask之app.route装饰器函数的参数
  • (每日一问)设计模式:设计模式的原则与分类——如何提升代码质量?
  • (三)mysql_MYSQL(三)