Node.js Express 中间件详解

发布于2026-03-26 14:06 阅读19次 
# Node.js Express 中间件详解
## 什么是中间件?
中间件(Middleware)是 Express 框架的核心概念,它是介于请求(Request)和响应(Response)之间的函数。中间件可以执行代码、修改请求和响应对象、结束请求-响应循环,或者调用下一个中间件。
Express 的中间件本质上是一个函数,它接收三个参数:req(请求对象)、res(响应对象)和 next(下一个中间件函数)。
## 中间件的工作原理
当我们发起一个 HTTP 请求时,Express 会按照定义的顺序依次执行中间件。每个中间件都可以:
1. 执行任何代码 - 比如日志记录、参数验证
2. 修改 req 和 res 对象 - 添加自定义属性或方法
3. 结束请求-响应循环 - 直接返回响应,不再调用 next()
4. 调用下一个中间件 - 通过 next() 传递控制权
## 中间件的分类
### 1. 应用级中间件
应用级中间件绑定到 app 对象,使用 app.use() 或 app.METHOD() 注册:
```javascript
// 匹配所有请求
app.use((req, res, next) => {
console.log(请求时间: ${new Date()});
next();
});
// 匹配特定路径
app.use('/api', (req, res, next) => {
console.log('API 请求');
next();
});
// 匹配特定 HTTP 方法
app.get('/users', (req, res) => {
res.json(users);
});
```
### 2. 路由级中间件
路由级中间件绑定到 express.Router(),用法与应用级中间件相同:
```javascript
const router = express.Router();
router.use((req, res, next) => {
console.log('路由中间件');
next();
});
router.get('/profile', (req, res) => {
res.send('用户资料');
});
app.use('/user', router);
```
### 3. 错误处理中间件
错误处理中间件有四个参数:err、req、res、next:
```javascript
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('服务器错误!');
});
```
### 4. 内置中间件
Express 自带几个内置中间件:
- express.static() - 托管静态文件
- express.json() - 解析 JSON 请求体
- express.urlencoded() - 解析 URL 编码的请求体
```javascript
app.use(express.static('public'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
```
### 5. 第三方中间件
社区提供了丰富的中间件:
- morgan - HTTP 日志
- cors - 跨域资源共享
- helmet - 安全头
- body-parser - 请求体解析
```javascript
const morgan = require('morgan');
const cors = require('cors');
app.use(morgan('dev'));
app.use(cors());
```
## 实际应用案例
### 日志记录中间件
```javascript
function logger(req, res, next) {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.url} - ${res.statusCode} - ${duration}ms`);
});
next();
}
app.use(logger);
```
### 身份验证中间件
```javascript
function authenticate(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({ error: '未授权' });
}
// 验证 token 的逻辑
const user = verifyToken(token);
if (!user) {
return res.status(403).json({ error: '无效的 token' });
}
req.user = user;
next();
}
app.use('/api/protected', authenticate);
```
### 请求限流中间件
```javascript
function rateLimiter(req, res, next) {
const ip = req.ip;
const now = Date.now();
if (!requests.has(ip)) {
requests.set(ip, [now]);
return next();
}
const times = requests.get(ip).filter(t => now - t < 60000);
if (times.length >= 100) {
return res.status(429).json({ error: '请求过于频繁' });
}
times.push(now);
requests.set(ip, times);
next();
}
app.use(rateLimiter);
```
## 中间件的执行顺序
中间件的执行顺序至关重要,定义顺序就是执行顺序:
```javascript
app.use((req, res, next) => {
console.log('1. 第一个中间件');
next();
});
app.use((req, res, next) => {
console.log('2. 第二个中间件');
next();
});
app.get('/', (req, res) => {
console.log('3. 路由处理器');
res.send('Hello');
});
```
## 注意事项
1. 永远不要忘记调用 next() - 除了最后一个中间件
2. 错误处理中间件要放在最后 - 确保能捕获所有错误
3. 中间件顺序很重要 - 把通用的中间件放在前面
4. 注意异步中间件 - 异步操作要在完成后才调用 next()
## 总结
中间件是 Express 灵活性和模块化的关键。通过合理组织中间件,我们可以模块化代码提高可维护性,复用通用逻辑如日志、认证、限流,构建强大的请求处理管道。掌握中间件的编写和使用,是成为 Express 高手的第一步。