第九篇 API设计原则与最佳实践
深入浅出HTTP请求前后端交互系列专题
第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述
第二章 HTTP请求方法、状态码详解与缓存机制解析
第三章 前端发起HTTP请求
第四章 前后端数据交换格式详解
第五章 跨域资源共享(CORS):现代Web开发中的关键机制
第六篇 提升网页性能:深入解析HTTP请求优化策略(一)
第七篇 提升网页性能:深入解析HTTP请求优化策略(二)
第八篇 提升网页性能:深入解析HTTP请求优化策略(三)
第九篇 API设计原则与最佳实践
第十篇 Axios最佳实战:前端HTTP通信的王者之选
第十一篇 前沿趋势与展望:深入探索GraphQL、RESTful API、WebSocket、SSE及QUIC与HTTP/3
文章目录
- API设计原则与最佳实践
- RESTful API设计原则
- 1. 资源导向
- a. 资源识别
- b. HTTP动词的使用
- 2. 状态转移
- 3. 统一接口
- 4. RESTful API 示例(axios调用)
- 5. 非RESTful API 示例(axios调用)
- HATEOAS理念与实践
- 1. Hypermedia as the Engine of Application State (HATEOAS)
- a. 原则阐述
- b. 实践举例
- API版本控制策略
- 1. 版本管理方法
- i. URL路径版本化
- ii. 请求头版本化
- iii. 查询参数版本化
- 错误处理与反馈设计
- 1. 错误处理机制
- a. HTTP状态码
- b. 错误响应格式
API设计原则与最佳实践
RESTful API设计原则
1. 资源导向
a. 资源识别
在REST架构风格中,API的设计围绕资源展开。每个URL代表一个可被唯一标识的资源,并且应当清晰、简洁和语义化。例如:
/api/users # 用户集合资源
/api/users/42 # 特定ID为42的用户资源
b. HTTP动词的使用
通过HTTP方法来定义对资源的操作:
GET:用于获取资源信息。POST:用于创建新资源。PUT:用于替换整个资源。PATCH:用于更新资源的部分内容。DELETE:用于删除资源。
2. 状态转移
API应遵循无状态通信原则,每次请求都应包含所有必要的信息以完成操作,服务器不保存客户端会话状态。
3. 统一接口
确保API的一致性,不同资源类型的处理方式应当遵从相同的模式。
为了更直观地体现RESTful API的优势,我们将通过使用axios库(一个流行的JavaScript HTTP客户端)来调用RESTful API和非RESTful API的示例进行对比。
4. RESTful API 示例(axios调用)
// 引入axios库
import axios from 'axios';// 创建RESTful API实例
const api = axios.create({baseURL: 'https://api.example.com/v1',
});// 调用RESTful API资源
async function createNewOrder(orderData) {try {// POST请求创建新订单const response = await api.post('/orders', orderData);return response.data;} catch (error) {console.error('Error creating order:', error.response.data);}
}async function updateOrderStatus(orderId, newStatus) {try {// PUT请求更新订单状态const url = `/orders/${orderId}`;const data = { status: newStatus };const response = await api.put(url, data);return response.data;} catch (error) {console.error('Error updating order status:', error.response.data);}
}async function deleteOrder(orderId) {try {// DELETE请求删除订单const url = `/orders/${orderId}`;await api.delete(url);} catch (error) {console.error('Error deleting order:', error.response.data);}
}// 使用示例
const newOrder = { /* 订单数据 */ };
createNewOrder(newOrder).then(createdOrder => console.log('Created order:', createdOrder));const orderIdToUpdate = '123';
const updatedStatus = 'shipped';
updateOrderStatus(orderIdToUpdate, updatedStatus).then(updatedOrder => console.log('Updated order:', updatedOrder));const orderIdToDelete = '456';
deleteOrder(orderIdToDelete).then(() => console.log('Deleted order with ID:', orderIdToDelete));
5. 非RESTful API 示例(axios调用)
// 同样引入axios库
import axios from 'axios';// 非RESTful API的调用方式
const nonRestApi = axios.create({baseURL: 'https://legacy.example.com/api',
});async function executeNonRestAction(action, data) {try {// 动作类型作为URL的一部分const url = `/${action}`;const response = await nonRestApi.post(url, data);return response.data;} catch (error) {console.error(`Error executing action ${action}:`, error.response.data);}
}async function createLegacyOrder(orderData) {try {const response = await executeNonRestAction('CreateNewOrder', orderData);return response;} catch (error) {console.error('Error creating legacy order:', error.response.data);}
}async function updateLegacyOrderStatus(orderId, newStatus) {try {const requestData = { orderId, status: newStatus };const response = await executeNonRestAction('UpdateOrderStatus', requestData);return response;} catch (error) {console.error('Error updating legacy order status:', error.response.data);}
}// 使用示例
const legacyOrder = { /* 订单数据 */ };
createLegacyOrder(legacyOrder).then(createdOrder => console.log('Created legacy order:', createdOrder));const legacyOrderId = '789';
const legacyUpdatedStatus = 'processing';
updateLegacyOrderStatus(legacyOrderId, legacyUpdatedStatus).then(updatedOrder => console.log('Updated legacy order:', updatedOrder));
优势对比:
-
清晰性与一致性:RESTful API中每个HTTP方法都对应着特定的操作意图,使得API的设计更加直观且易于理解。例如,在RESTful API中,
POST /orders明确表示创建新订单,而PUT /orders/:id则用于更新订单,结构一致,无需额外记忆特殊动作名。 -
可扩展性与维护性:随着系统的发展,RESTful API可以轻松添加新的资源或资源操作,因为它们遵循统一的模式。而非RESTful API在新增功能时可能需要不断调整URL路径和动作命名规则。
-
工具支持与缓存机制:许多开发工具和网络基础设施针对RESTful API设计提供了更好的支持,如自动补全、接口文档生成器等。此外,RESTful API更容易利用HTTP协议的缓存特性,如响应头中的Cache-Control、ETag等字段,提升性能。
-
版本控制与兼容性:RESTful API可以通过URI路径或Accept头等方式实现版本控制,从而方便地处理升级过程中的兼容问题。非RESTful API在没有明确版本管理的情况下可能会带来更复杂的升级挑战。
通过上述对比,可以看出RESTful API在设计原则、开发者体验、长期维护以及与现有Web标准的契合度等方面具有显著优势。
HATEOAS理念与实践
1. Hypermedia as the Engine of Application State (HATEOAS)
a. 原则阐述
HATEOAS是REST的核心特性之一,它意味着API响应中应该包含足够的链接信息,使得客户端可以通过这些链接发现接下来可以执行的动作,而无需预知具体URL。
例如,在一个电商应用中,当客户端请求一个订单资源时,服务器返回的JSON响应不仅包含订单详情,还会包括链接到相关操作的URL,如:
{"id": "12345","customer": "John Doe","status": "pending","total": "$100.00","_links": {"self": { "href": "/orders/12345" },"cancel": { "href": "/orders/12345/cancel", "method": "POST" },"pay": { "href": "/orders/12345/pay", "method": "POST" },"items": { "href": "/orders/12345/items" }}
}
在这个例子中,_links属性定义了几个链接:
self:指向当前订单资源自身的URL。cancel和pay:分别指示了取消订单和支付订单的操作,通过POST方法触发这些动作,并给出了对应的动作URL。items:指向与当前订单相关的商品列表资源。
这样的设计允许客户端根据接收到的数据结构动态发现并导航到不同的资源和状态,无需硬编码URL或者了解整个API的结构。这使得API更加灵活、可扩展且易于维护,同时增强了客户端的适应性,因为它们可以根据服务器提供的上下文信息来决定下一步的操作。
b. 实践举例
{"user": {"id": 42,"name": "Alice","_links": {"self": { "href": "/api/users/42" },"edit": { "href": "/api/users/42/edit" },"orders": { "href": "/api/users/42/orders" }}}
}
在这个示例中,API返回的数据包含了指向当前用户资源、编辑资源以及该用户订单集合的链接,允许客户端通过解析这些链接来进行导航和交互。
在遵循HATEOAS原则的RESTful API设计中,_links或类似结构中的键(keys)并不是随意生成的,而是根据资源间关系和操作意图来命名的。例如,“self”、“next”、“prev”、“create”、"update"等都是常见的链接关系名称,它们具有一定的语义意义,客户端可以根据这些名称理解链接的目的。
对于前端来说,确实需要处理这一层额外的信息,但这样做的好处在于:
-
动态发现:客户端无需预先知道所有可能的接口地址或者API的变化,只需要解析返回的链接信息就能找到下一步操作的入口。
-
可扩展性:当API进行版本升级或添加新的功能时,只要保持链接关系的约定不变,前端应用可以继续正常工作,无需硬编码新的URL。
-
松耦合:前后端之间的耦合度降低,后端服务架构可以独立演化而不影响前端用户体验。
至于是否需要存储这个信息以便以后使用,这取决于具体的业务需求。有些情况下,客户端可能需要临时缓存部分链接以实现页面间的跳转或者异步操作;而在其他场景下,客户端可能会立即利用这些链接执行后续请求,并不需要持久化存储。通常,在构建响应式前端应用时,会根据当前状态和用户交互实时处理接收到的链接信息,而不是静态地存储全部链接数据。
API版本控制策略
1. 版本管理方法
i. URL路径版本化
将版本号嵌入到URL路径中,如:
/v1/users
/v2/users
ii. 请求头版本化
通过HTTP请求头传递版本信息,例如:
Accept: application/vnd.example-com.user+json;version=1.0
iii. 查询参数版本化
也可以选择将版本号作为查询参数传递:
/api/users?version=1
错误处理与反馈设计
1. 错误处理机制
a. HTTP状态码
正确使用HTTP状态码传达请求结果的状态,如4xx系列表示客户端错误,5xx系列表示服务器端错误。
b. 错误响应格式
提供统一且详细的错误消息体,通常是一个JSON对象,包括错误代码、描述信息、可能的话还包含解决问题的建议或指向帮助文档的链接。
{"error": "BadRequest","message": "Missing required parameter 'username'","status_code": 400,"more_info": "https://docs.example.com/errors/400"
}
通过遵循以上设计原则与最佳实践,开发者能够构建出易于理解和使用的RESTful API,并确保其在版本迭代和异常处理时具备良好的扩展性和可靠性。
相关文章:
第九篇 API设计原则与最佳实践
深入浅出HTTP请求前后端交互系列专题 第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述 第二章 HTTP请求方法、状态码详解与缓存机制解析 第三章 前端发起HTTP请求 第四章 前后端数据交换格式详解 第五章 跨域资源共享(CORS):现代W…...
新版AndroidStudio配置maven阿里云镜像
project下的build.gradle: // Top-level build file where you can add configuration options common to all sub-projects/modules. // 注意jdk版本需要17以上,因为8.1.3的gradle需要jdk17以上 //plugins { // id com.android.application version…...
【OSG案例详细分析与讲解】之十一:【多效果的3D动画】
目录 一、【多效果的3D动画】前言 二、【多效果的3D动画】实现效果...
一道使用LinkedList和Stack解决的算法题
一、无法吃午餐的学生数量 学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。 餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮&#…...
通用外设-W25Q64
前言 一、SPI通信 二、W25Q64基初时序 1.各种命令代码 2.代码 1.写使能指令 2.读取芯片是否忙碌状态并等待 3.写入数据 4.擦除函数操作 5.读取代码 三.验证 四.擦除说明 总结 前言 在单片机中一般32K FLASH就够用了,但是当我们使用图片或其他大量数据时…...
Spring MVC MVC介绍和入门案例
1.SpringMVC概述 1.1.MVC介绍 MVC是一种设计模式,将软件按照模型、视图、控制器来划分: M:Model,模型层,指工程中的JavaBean,作用是处理数据 JavaBean分为两类: 一类称为数据承载Bean…...
android使用ndk开发
ndk ndk sdk要单独下载和android sdk不同 https://developer.android.google.cn/ndk/downloads?hl=zh-cn 解压后添加ndk路径到path即可 gradle gradle下载太慢使用国内镜像 distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-6.7.1-all.zip 执行gradlew.ba…...
行为型设计模式——模板方法模式
学习难度:⭐ ,比较常用 模板方法模式 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知࿰…...
曲面上偏移命令的查找
今天学习老王的SW绘图时,遇到一个命令找不到,查询了一会终于找到了这个命令,防止自己忘记,特此记录一下,这个命令就是“曲面上偏移”,网上好多的教程都是错误的,实际上这个命令没有在曲面里面&a…...
世邦spon IP网络对讲广播系统任意文件上传漏洞
产品介绍 世邦通信IP网络对讲广播系统采用领先的IPAudio™技术,将音频信号以数据包形式在局域网和广域网上进行传送,是一套纯数字传输系统。 漏洞描述 spon IP网络对讲广播系统存在任意文件上传漏洞,攻击者可以通过构造特殊请求包上传恶意后门文件,从…...
mp4文件全部转换为mp3
问题 今天突发奇想,想把mp4视频转换为mp3来收听,于是想到了ffmpeg工具 步骤 安装ffmpeg环境 要在 Windows 上配置 FFmpeg 环境,你可以按照以下步骤进行操作: 下载 FFmpeg: 首先,你需要下载 FFmpeg 的 W…...
深信服技术认证“SCSA-S”划重点:逻辑漏洞
为帮助大家更加系统化地学习网络安全知识,以及更高效地通过深信服安全服务认证工程师考核,深信服特别推出“SCSA-S认证备考秘笈”共十期内容,“考试重点”内容框架,帮助大家快速get重点知识~ 划重点来啦 *点击图片放大展示 深信服…...
Linux grep命令教程:强大的文本搜索工具(附案例详解和注意事项)
Linux grep命令介绍 grep (Global Regular Expression Print)命令用来在文件中查找包含或者不包含某个字符串的行,它是强大的文本搜索工具,并可以使用正则表达式进行搜索。当你需要在文件或者多个文件中搜寻特定信息时,grep就显得无比重要啦…...
网络安全的威胁PPT
建议的PPT免费模板网站:http://www.51pptmoban.com/ppt/ 此PPT模板下载地址:https://file.51pptmoban.com/d/file/2023/03/20/1ae84aa8a9b666d2103f19be20249b38.zip 内容截图:...
CUDA驱动深度学习发展 - 技术全解与实战
全面介绍CUDA与pytorch cuda实战 关注TechLead,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士&…...
如何做用户分层和标签体系
“活动作了一场接一场,简直要累死了,拉进来的客户也没有多少,投入产出完全不成比例,怎么办?“ “有那么多注册用户,但是GMV怎么才这么点,他们怎么不买啊,难道都是羊毛党?…...
Vue+Element Ui实现el-table自定义表头下拉选择表头筛选
用vueelement ui开发管理系统时,使用el-table做表格,当表格列过多的时候,想要做成可选表头的,实现表格列的筛选显示,效果如下: 代码文件结构: 废话不多说,直接上代码: 第…...
使用Java连接MongoDB (6.0.12) 报错
报错: Exception in thread "main" com.mongodb.MongoCommandException: Command failed with error 352: Unsupported OP_QUERY command: create. 上图中“The client driver may require an upgrade”说明了“客户端驱动需要进行升级”,解…...
数学建模day16-预测模型
本讲首先将介绍灰色预测模型,然后将简要介绍神经网络在数据预测中的应用,在本讲的最 后,我将谈谈清风大佬对于数据预测的一些看法。 注:本文源于数学建模学习交流相关公众号观看学习视频后所作 目录 灰色系统 GM(1,1)…...
Vue3响应式系统(一)
一、副作用函数。 副作用函数指的是会产生副作用的函数。例如:effect函数会直接或间接影响其他函数的执行,这时我们便说effect函数产生了副作用。 function effect(){document.body.innerText hello vue3 } 再例如: //全局变量let val 2f…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
2025.6.9总结(利与弊)
凡事都有两面性。在大厂上班也不例外。今天找开发定位问题,从一个接口人不断溯源到另一个 接口人。有时候,不知道是谁的责任填。将工作内容分的很细,每个人负责其中的一小块。我清楚的意识到,自己就是个可以随时替换的螺丝钉&…...
