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

第九篇 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。
  • cancelpay:分别指示了取消订单和支付订单的操作,通过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"等都是常见的链接关系名称,它们具有一定的语义意义,客户端可以根据这些名称理解链接的目的。

对于前端来说,确实需要处理这一层额外的信息,但这样做的好处在于:

  1. 动态发现:客户端无需预先知道所有可能的接口地址或者API的变化,只需要解析返回的链接信息就能找到下一步操作的入口。

  2. 可扩展性:当API进行版本升级或添加新的功能时,只要保持链接关系的约定不变,前端应用可以继续正常工作,无需硬编码新的URL。

  3. 松耦合:前后端之间的耦合度降低,后端服务架构可以独立演化而不影响前端用户体验。

至于是否需要存储这个信息以便以后使用,这取决于具体的业务需求。有些情况下,客户端可能需要临时缓存部分链接以实现页面间的跳转或者异步操作;而在其他场景下,客户端可能会立即利用这些链接执行后续请求,并不需要持久化存储。通常,在构建响应式前端应用时,会根据当前状态和用户交互实时处理接收到的链接信息,而不是静态地存储全部链接数据。

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&#xf…...

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…...

行为型设计模式——模板方法模式

学习难度:⭐ ,比较常用 模板方法模式 在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知&#xff0…...

曲面上偏移命令的查找

今天学习老王的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…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...

【机器视觉】单目测距——运动结构恢复

ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛&#xf…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来&#xf…...

零基础设计模式——行为型模式 - 责任链模式

第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...