【express-generator】05-路由中间件和错误处理(第一阶段收尾)
一、前言
上篇文章我们介绍了express-generator的请求体解析,重点讲了常用的请求体数据格式(JSON/URL 编码的表单数据)以及一个FILE文件上传,同时搭配代码示范进行辅助理解。
二、本篇重点
我们继续第一阶段的知识,本篇把最后两个知识点(路由中间件和错误请求)讲完,顺利完成第一阶段的初步认识和学习。
三、知识点:路由中间件
1、路由中间件是什么?
路由中间件是 Express 中的一个强大功能,它允许你在处理请求之前和之后执行自定义逻辑。中间件可以用于各种任务,如日志记录、身份验证、数据验证等。
路由中间件可以被理解为一个函数,它接收三个参数:
req
(请求对象)、res
(响应对象)和next
(函数)。这个函数可以对这三个参数进行操作,并且通过这些操作来影响 Express 服务器的行为。以下是路由中间件的一些关键点:
接收参数:
req
(请求对象):包含了请求的所有信息,如请求方法、URL、请求头、请求体等。中间件可以读取和修改req
对象的属性。res
(响应对象):用于向客户端发送响应。中间件可以发送响应、设置响应头、设置响应状态码等。next
(函数):调用next()
可以将控制权传递给下一个中间件或路由处理函数。如果不调用next()
,请求处理流程将停止。操作和影响:
- 读取和修改请求信息:中间件可以读取请求中的数据,如解析请求体、获取请求头信息等。也可以修改请求对象,如添加自定义属性、修改请求参数等。
- 发送响应:中间件可以直接向客户端发送响应,结束请求处理流程。例如,可以发送错误响应、重定向响应等。
- 执行自定义逻辑:中间件可以执行各种自定义逻辑,如身份验证、日志记录、数据验证、缓存处理等。
- 错误处理:中间件可以捕获和处理错误,将错误传递给错误处理中间件,或者直接发送错误响应。
中间件的执行顺序
- 顺序执行:中间件按照它们在
app.use()
中被调用的顺序执行。每个中间件都有机会处理请求,并决定是否将控制权传递给下一个中间件。- 调用
next()
:中间件通过调用next()
函数来将控制权传递给下一个中间件。如果中间件不调用next()
,请求处理流程将停止,不会执行后续的中间件或路由处理函数。
2、express-generator创建express应用程序,默认使用的路由中间件
首先让我们看看使用express-generator创建一个express应用程序时,app.js默认使用的路由中间件有哪些
知识点相关介绍:
1.
logger('dev')
- 作用:使用
morgan
日志记录器中间件,记录 HTTP 请求的详细信息。- 配置:
'dev'
是morgan
的预定义格式之一,它会在开发环境中提供简洁的彩色日志输出,包括请求方法、URL、响应状态码和响应时间等。- 使用场景:用于开发环境中的日志记录,帮助开发者监控和调试应用程序。
2.
express.json()
- 作用:解析 JSON 格式的请求体。
- 使用场景:用于处理客户端发送的 JSON 数据,例如 API 请求中的 JSON 数据。
3.
express.urlencoded({ extended: false })
- 作用:解析 URL 编码的请求体。
- 配置:
{ extended: false }
表示使用内置的查询字符串解析器,它只能解析简单的键值对,不支持嵌套对象或数组。- 使用场景:用于处理 HTML 表单提交的数据,这些数据通常以
application/x-www-form-urlencoded
格式发送。4.
cookieParser()
- 作用:解析客户端发送的 Cookie。
- 使用场景:用于处理客户端发送的 Cookie,以便在服务器端进行身份验证或其他需要 Cookie 的操作。
5.
express.static(path.join(__dirname, 'public'))
- 作用:提供静态文件服务。
- 配置:
path.join(__dirname, 'public')
指定了静态文件的目录,通常是项目的public
目录。- 使用场景:用于提供网站的静态资源,如图片、CSS、JavaScript 文件等,使得客户端可以直接访问这些文件。
3、动手写一个简单的路由中间件
const express = require('express');
const app = express();// 定义一个日志记录中间件
function logRequest(req, res, next) {const { method, url } = req;console.log(`Received ${method} request for ${url}`);next(); // 调用下一个中间件
}// 使用中间件
app.use(express.json()) //解析请求体数据
app.use(logRequest); //日志记录中间件
app.get('/', (req, res) => {res.send('Hello, World!');
});
app.post('/user', (req, res) => {console.log("接收的请求体参数>>>",req.body);res.send(req.body);});app.listen(3009, () => {console.log('Server is running on port 3009');
});
启动服务器,打开apipost工具进行路由测试
在这个示例中,
logRequest
中间件会在每个请求到达时记录请求方法和 URL。
四、知识点:错误处理
错误处理是任何 Web 应用程序的重要组成部分。在 Express 中,错误处理中间件用于捕获和处理在请求处理过程中发生的错误。
常用知识点
- 错误处理中间件:必须有四个参数:
err
、req
、res
和next
。- 抛出错误:在中间件或路由处理函数中使用
next(err)
来传递错误。- 自定义错误对象:可以创建自定义错误对象以提供更详细的错误信息。
1、常见的错误类型
- 语法错误:由于代码编写错误导致的错误,如拼写错误、语法不正确等。
- 运行时错误:在代码执行过程中发生的错误,如访问未定义的变量、调用不存在的方法等。
- HTTP 错误:与 HTTP 请求和响应相关的错误,如 404(未找到)、500(服务器内部错误)等。
- 输入验证错误:由于用户输入不符合预期格式或规则导致的错误。
- 数据库错误:与数据库操作相关的错误,如查询失败、连接错误等。
2、错误处理中间件
错误处理中间件是 Express 中用于处理错误的特殊中间件。它有四个参数:
err
、req
、res
和next
。当在中间件或路由处理函数中调用next(err)
时,控制权会传递给错误处理中间件。
一个简单的代码示范
const express = require('express');
const app = express();// 模拟一个路由处理函数,可能会抛出错误
app.get('/error', (req, res, next) => {const error = new Error('Something went wrong!');error.status = 500; // 设置 HTTP 状态码next(error); // 将错误传递给错误处理中间件
});// 错误处理中间件
app.use((err, req, res, next) => {console.error(err.stack); // 记录错误堆栈res.status(err.status || 500).json({error: {message: err.message}});
});app.listen(3009, () => {console.log('Server is running on port 3009');
});
启动服务器,在apipost工具中进行测试。
点击发送,得到结果
3、自定义错误对象
自定义错误对象可以帮助我们更清晰地表示特定类型的错误,并提供额外的上下文信息。
以下是一个自定义错误对象的简单代码示范。
const express = require('express');
const app = express();// 自定义错误类
class CustomError extends Error {constructor(message, status) {super(message);this.status = status;this.name = 'CustomError';}
}// 模拟路由 1:抛出自定义错误
app.get('/custom-error', (req, res, next) => {const error = new CustomError('Custom error occurred', 400);next(error);
});// 模拟路由 2:抛出普通错误
app.get('/error', (req, res, next) => {const error = new Error('Something went wrong!');error.status = 500;next(error);
});// 错误处理中间件
app.use((err, req, res, next) => {console.error(err.stack);res.status(err.status || 500).json({error: {message: err.message,name: err.name}});
});app.listen(3009, () => {console.log('Server is running on port 3009');
});
启动服务,打开apipost攻击进行测试
五、总结
至此,我们初步完成第一阶段的所有知识学习以及练习。多动手实践,举一反三,希望文章的案例会对大家有所帮助。
接下来的文章,我们接着第二阶段的知识学习以及代码案例练习。第二阶段的大纲如下:
第二阶段:进阶与应用
如果你喜欢这篇文章,请点赞收藏。
关注我,获取前端更多使用知识。
最近业务需求多,会比较忙,但我也会抽出时间进行更新文章,敬请期待。
相关文章:

【express-generator】05-路由中间件和错误处理(第一阶段收尾)
一、前言 上篇文章我们介绍了express-generator的请求体解析,重点讲了常用的请求体数据格式(JSON/URL 编码的表单数据)以及一个FILE文件上传,同时搭配代码示范进行辅助理解。 二、本篇重点 我们继续第一阶段的知识,…...
Linux环境下确认并操作 Git 仓库
在软件开发和版本控制中,Git 已成为不可或缺的工具。有时,我们需要确认某个目录是否是一个 Git 仓库,并在该目录中运行脚本。本文将详细介绍如何确认 /usr/local/src/zcxt/backend/policy-system-backend 目录是否是一个 Git 仓库,…...

UDP -- 简易聊天室
目录 gitee(内有详细代码) 图解 MessageRoute.hpp UdpClient.hpp UdpServer.hpp Main.hpp 运行结果(本地通信) 如何分开对话显示? gitee(内有详细代码) chat_room zihuixie/Linux_Lear…...

NVIDIA在CES 2025上的三大亮点:AI芯片、机器人与自动驾驶、全新游戏显卡
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

【通俗理解】AI的两次寒冬:从感知机困局到深度学习前夜
AI的两次寒冬:从感知机困局到深度学习前夜 引用(中英双语) 中文: “第一次AI寒冬,是因为感知机局限性被揭示,让人们失去了对算法可行性的信心。” “第二次AI寒冬,则是因为专家系统的局限性和硬…...

transformer深度学习实战CCTSDB中国交通标志识别
本文采用RT-DETR作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。RT-DETR以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对CCTSDB交通标志数据集进行训练和优化,该数据集包含丰富的CCTSDB交…...

JavaWeb开发(六)XML介绍
1. XML介绍 1.1. 什么是XML (1)XML 指可扩展标记语言(EXtensible Markup Language)XML 是一种很像HTML的标记语言。 (2)XML 的设计宗旨是传输数据(目前主要是作为配置文件),而不是显示数据。 (3&a…...
使用pbootcms开发一个企业官网
V:llike620 pbootcms开源PHP建站系统 https://www.pbootcms.com/ 配置网站 域名解析后,网站绑定到程序根目录即可 例如:本地域名是dobot.test ,那么也要同步本地的hosts是 127.0.0.1 dobot.test 需要配置下伪静态规则 location / {if (!-e $r…...

Linux C编程——文件IO基础
文件IO基础 一、简单的文件 IO 示例二、文件描述符三、open 打开文件1. 函数原型2. 文件权限3. 宏定义文件权限4. 函数使用实例 四、write 写文件五、read 读文件六、close 关闭文件七、Iseek 绍 Linux 应用编程中最基础的知识,即文件 I/O(Input、Outout…...
【信息系统项目管理师】高分论文:论信息系统项目的风险管理(人民医院的信息系统)
更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文1、规划风险管理2、项目风险识别3、风险定性分析4、风险定量分析5、制定风险应对6、实施风险应对计划7、监督风险论文 2022年6月,我作为项目经理承担了XX县人民医院的信息系统建设,该项目总投资300万,其…...

UE播放声音
蓝图中有两个播放声音的函数 Play Sound 2D 和 Play Sound at Location Play Sound 2D没有声音距离衰减,一般用于界面ui Play Sound at Location 有声音距离衰减,一般用于枪声,场景声等,比较常用...
Docker Compose 启动 Harbor 并指定网络
1. 介绍 Harbor 是一个开源的企业级 Docker 镜像仓库,提供镜像存储、访问控制、安全扫描等功能。使用 Docker Compose 启动 Harbor 时,您可以指定一个自定义网络,以便管理容器之间的网络通信。在本示例中,我们将创建一个名为 har…...
WebSocket 实战案例:从设计到部署
在前六篇文章中,我们深入探讨了 WebSocket 的基础原理、服务端开发、客户端实现、安全实践、性能优化和测试调试。今天,让我们通过一个实战案例,看看如何将这些知识应用到实际项目中。我曾在一个大型在线教育平台中,通过 WebSocket 实现了实时互动课堂,支持了数万名师生的同时在…...
selenium合集
环境搭建步骤 安装selenium pip install selenium 安装浏览器 安装浏览器驱动 谷歌浏览器:chromdriver.exe ie浏览器:ieserverdriver.exe FireFox浏览器:geckodriver.exe 特别注意⚠️:下载驱动版本必须与浏览器版本一致 下载地址 淘宝镜像࿱…...
JVM生产环境常用参数配置及调优建议
一、生产常用参数配置 JAVA_OPTS"-server -Xms3000m -Xmx3000m -Xmn1500m -XX:UseG1GC -XX:ConcGCThreads8 -XX:PrintGCDetails -XX:PrintGCTimeStamps -Xloggc:./g1-gc.log -XX:MaxMetaspaceSize256m -XX:-UseGCOverheadLimit -XX:UseCompressedOops -XX:HeapDumpOnOu…...
Spring Boot 3 实现 MySQL 主从数据库之间的数据同步
✅ Spring Boot 3 实现 MySQL 主从数据库之间的数据同步 在实际项目中,为了提高 系统的读性能 和 数据的可用性,通常会使用 主从数据库架构。Spring Boot 提供了对 多数据源 的良好支持,可以轻松配置 主从数据库 的数据同步,实现…...

【小程序开发】- 小程序版本迭代指南(版本发布教程)
一,版本号 版本号是小程序版本的标识,通常由一系列数字组成,如 1.0.0、1.1.0 等。版本号的格式通常是 主版本号.次版本号.修订号 主版本号:当小程序有重大更新或不兼容的更改时,主版本号会增加。 次版本号:…...
MySQL 间隙锁避免“可重复读”出现“幻读”
在数据库事务处理中,可重复读(Repeatable Read)是一个常用的隔离级别,但其默认行为可能导致幻读现象。然而,在 MySQL 的实现中,通过 **间隙锁(Gap Lock)**机制,能够避免幻…...

揭秘区块链隐私黑科技:零知识证明如何改变未来
文章目录 1. 引言:什么是零知识证明?2. 零知识证明的核心概念与三大属性2.1 完备性(Completeness)2.2 可靠性(Soundness)2.3 零知识性(Zero-Knowledge) 3. 零知识证明的工作原理4. 零…...
JavaWeb开发:从入门到精通
近年来,JavaWeb开发已经成为了互联网开发领域的重要技术之一。无论是大型企业还是个人项目,都离不开JavaWeb开发。本文将为您介绍JavaWeb开发的基本概念、常用技术和开发流程,帮助您快速入门并掌握这一技术。 一、JavaWeb开发的基本概念 Jav…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...