在Node.js的Express框架中,中间件是一个核心概念。简单来说,中间件是一个函数,它拦截HTTP请求,在请求到达路由处理之前或响应发送给客户端之前执行一些逻辑操作。Express应用的整个请求处理过程本质上是一条中间件链——每个请求都会依次经过这些中间件函数,最后到达路由处理器(如果有的话)。
1. 中间件的标准形式与核心作用
中间件函数接收三个参数:req(请求对象)、res(响应对象)、next(下一个中间件函数)。典型写法如下:
- function middleware(req, res, next) {
- // 处理逻辑:如请求解析、身份校验、日志记录等
- next(); // 将控制权传递给下一个中间件或路由
- }
复制代码
核心作用主要有两点:
- 在请求到达具体路由之前执行操作(如解析请求体、校验Token、添加请求头)。
- 在响应发送之前执行操作(如记录日志、压缩响应、添加CORS头)。
通过next()函数,中间件可以决定是否继续往下传递。如果不调用next(),请求会挂起;如果调用next(err),则直接跳转到错误处理中间件。
2. 中间件的五大分类
2.1 应用程序级中间件
通过app.use()挂载到Express应用实例上,作用于全局或匹配特定路径。常用于统一处理:JSON解析、日志、安全验证等。
- const express = require('express');
- const app = express();
- // 内置中间件:解析JSON请求体
- app.use(express.json());
- // 自定义全局日志中间件
- app.use((req, res, next) => {
- console.log(`[${Date.now()}] ${req.method} ${req.url}`);
- next();
- });
复制代码
2.2 路由级中间件
挂载在express.Router()实例上,仅作用于当前路由模块,适合模块化组织业务逻辑。
- const router = express.Router();
- // 路由级中间件:仅对/users模块生效
- router.use((req, res, next) => {
- console.log('进入用户模块');
- next();
- });
- // 将路由挂载到应用上,路径前缀为/users
- app.use('/users', router);
复制代码
2.3 错误处理中间件
专门捕获并处理错误,必须接收四个参数:err、req、res、next。当任何中间件或路由调用next(err)时,Express会跳过所有普通中间件,直接执行这个错误处理中间件。
- app.use((err, req, res, next) => {
- res.send({
- status: 1,
- msg: err instanceof Error ? err.message : err,
- });
- });
复制代码
注意:错误处理中间件必须放在所有路由之后定义,否则无法捕获到错误。
2.4 内置中间件
Express原生提供,无需额外安装,直接通过express.xxx()使用。常见的有:
- express.static('public'):托管静态资源文件。
- express.json():解析Content-Type为application/json的请求体。
- express.urlencoded({ extended: true }):解析URL-encoded格式的请求体(通常是表单提交数据)。
2.5 第三方中间件
由社区开发,通过npm安装,扩展Express功能。
- cors:解决跨域问题。
- multer:处理文件上传。
- express-validator:数据验证。
- morgan:HTTP请求日志记录。
这些中间件一般遵循相同的(req, res, next)签名,使用前安装并导入即可:
- const cors = require('cors');
- app.use(cors());
复制代码
3. 实战要点与理解
- 中间件顺序至关重要:Express按代码顺序执行中间件。全局中间件(如JSON解析、日志)应放在最前面,路由中间件在中间,错误处理中间件放在最后。
- 每个中间件必须调用next()或发送响应(如res.json()),否则请求会挂死。
- 内置中间件express.json()和express.urlencoded()分别处理JSON和表单数据,若同时需要两者,都需注册。
掌握这些分类与用法,就能灵活地利用中间件机制进行模块化、可复用的Express应用开发。 |