Express.js中间件开发(2026-03-27)


文档摘要

Express.js中间件开发指南 概述 Express.js是基于Node.js的Web应用框架,其中间件机制是其核心特性。中间件函数可以访问请求对象(req)、响应对象(res)和next函数,在请求-响应周期中执行特定功能。本文介绍Express中间件的原理、类型和开发方法。 中间件基础 中间件函数结构 中间件类型 应用级中间件:绑定到app实例 路由级中间件:绑定到express.Router() 错误处理中间件:4个参数(err, req, res, next) 内置中间件:express.static、express.

Express.js中间件开发指南

概述

Express.js是基于Node.js的Web应用框架,其中间件机制是其核心特性。中间件函数可以访问请求对象(req)、响应对象(res)和next函数,在请求-响应周期中执行特定功能。本文介绍Express中间件的原理、类型和开发方法。

中间件基础

中间件函数结构

function middleware(req, res, next) { // 处理逻辑 console.log('中间件执行'); next(); // 调用下一个中间件 }

中间件类型

  1. 应用级中间件:绑定到app实例
  2. 路由级中间件:绑定到express.Router()
  3. 错误处理中间件:4个参数(err, req, res, next)
  4. 内置中间件:express.static、express.json等
  5. 第三方中间件:body-parser、cors等

应用级中间件

基本使用

const express = require('express'); const app = express(); // 全局中间件 app.use((req, res, next) => { console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`); next(); }); // 路径匹配中间件 app.use('/api', (req, res, next) => { console.log('API请求'); next(); }); // 路由处理 app.get('/', (req, res) => { res.send('Hello World'); }); app.listen(3000);

多个中间件

app.use(middleware1); app.use(middleware2); app.use(middleware3); function middleware1(req, res, next) { console.log('中间件1'); next(); } function middleware2(req, res, next) { console.log('中间件2'); next(); } function middleware3(req, res, next) { console.log('中间件3'); next(); } // 执行顺序:middleware1 -> middleware2 -> middleware3 -> 路由处理

路由级中间件

Router中间件

const express = require('express'); const router = express.Router(); // 路由级中间件 router.use((req, res, next) => { console.log('Router中间件'); next(); }); router.get('/', (req, res) => { res.send('Router首页'); }); router.get('/users', (req, res) => { res.send('用户列表'); }); module.exports = router; // app.js const userRouter = require('./routes/users'); app.use('/users', userRouter);

特定路由中间件

// 验证中间件 function authenticate(req, res, next) { const token = req.headers.authorization; if (!token) { return res.status(401).json({ error: '未授权' }); } // 验证token req.user = { id: 1, name: '张三' }; next(); } // 应用到特定路由 app.get('/protected', authenticate, (req, res) => { res.json({ message: '受保护的资源', user: req.user }); });

错误处理中间件

基本错误处理

// 错误处理中间件(4个参数) app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: '服务器内部错误', message: err.message }); }); // 触发错误 app.get('/error', (req, res) => { throw new Error('这是一个错误'); }); // 或使用next传递错误 app.get('/error', (req, res, next) => { const error = new Error('这是一个错误'); next(error); });

异步错误处理

// 方法1:使用try-catch app.get('/async', async (req, res, next) => { try { const data = await fetchData(); res.json(data); } catch (error) { next(error); } }); // 方法2:包装函数 function asyncHandler(fn) { return (req, res, next) => { Promise.resolve(fn(req, res, next)).catch(next); }; } app.get('/async', asyncHandler(async (req, res) => { const data = await fetchData(); res.json(data); }));

常用中间件开发

日志中间件

function logger(req, res, next) { const start = Date.now(); // 记录请求信息 console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); // 监听响应完成事件 res.on('finish', () => { const duration = Date.now() - start; console.log(`[${new Date().toISOString()}] ${req.method} ${req.url} - ${res.statusCode} - ${duration}ms`); }); next(); } app.use(logger);

认证中间件

function authenticate(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader) { return res.status(401).json({ error: '缺少认证信息' }); } const token = authHeader.split(' ')[1]; try { // 验证token(这里使用JWT示例) const jwt = require('jsonwebtoken'); const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (error) { res.status(401).json({ error: '无效的token' }); } } app.use('/api/protected', authenticate);

CORS中间件

function cors(req, res, next) { // 允许的源 res.header('Access-Control-Allow-Origin', '*'); // 允许的方法 res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); // 允许的头部 res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 预检请求 if (req.method === 'OPTIONS') { return res.sendStatus(200); } next(); } app.use(cors);

请求验证中间件

function validateRequest(schema) { return (req, res, next) => { const { error } = schema.validate(req.body); if (error) { return res.status(400).json({ error: '请求参数验证失败', details: error.details }); } next(); }; } // 使用 const Joi = require('joi'); const userSchema = Joi.object({ name: Joi.string().min(3).max(30).required(), email: Joi.string().email().required(), age: Joi.number().integer().min(18).max(100) }); app.post('/users', validateRequest(userSchema), (req, res) => { res.json({ message: '用户创建成功' }); });

限流中间件

const rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 限制100次请求 message: '请求过于频繁,请稍后再试', standardHeaders: true, legacyHeaders: false, }); app.use('/api/', limiter);

缓存中间件

const NodeCache = require('node-cache'); const cache = new NodeCache({ stdTTL: 600 }); // 10分钟缓存 function cacheMiddleware(duration = 600) { return (req, res, next) => { const key = req.originalUrl || req.url; const cached = cache.get(key); if (cached) { console.log('从缓存返回数据'); return res.json(cached); } // 劫持res.json方法 const originalJson = res.json.bind(res); res.json = function(data) { cache.set(key, data, duration); return originalJson(data); }; next(); }; } app.get('/api/data', cacheMiddleware(300), async (req, res) => { const data = await fetchData(); res.json(data); });

请求体解析中间件

// Express 4.x 需要body-parser const bodyParser = require('body-parser'); app.use(bodyParser.json()); // 解析JSON app.use(bodyParser.urlencoded({ extended: true })); // 解析URL编码 // Express 4.16+ 内置 app.use(express.json()); app.use(express.urlencoded({ extended: true }));

静态文件服务中间件

// 基本使用 app.use(express.static('public')); // 指定虚拟路径 app.use('/static', express.static('public')); // 多个静态目录 app.use('/static', express.static('public')); app.use('/uploads', express.static('uploads')); // 自定义静态文件服务 function staticFiles(root, options = {}) { const fs = require('fs'); const path = require('path'); return (req, res, next) => { const filePath = path.join(root, req.path); fs.access(filePath, fs.constants.F_OK, (err) => { if (err) { return next(); } res.sendFile(filePath, options, (err) => { if (err) { next(err); } }); }); }; } app.use('/assets', staticFiles('public/assets'));

中间件最佳实践

1. 中间件顺序很重要

// 正确的顺序 app.use(logger); // 1. 日志 app.use(express.json()); // 2. 解析请求体 app.use(cors); // 3. CORS app.use(authenticate); // 4. 认证 app.use(routes); // 5. 路由 app.use(errorHandler); // 6. 错误处理

2. 中间件应该单一职责

// 好的实践 app.use(authMiddleware); app.use(rateLimiter); app.use(cacheMiddleware); // 不好的实践 app.use((req, res, next) => { authenticate(req); rateLimit(req); cache(req, res); next(); });

3. 使用中间件链

app.get('/api/users', authenticate, // 1. 认证 authorize('admin'), // 2. 授权 validateRequest(userSchema), // 3. 验证 cacheMiddleware(), // 4. 缓存 async (req, res) => { // 5. 处理 const users = await User.find(); res.json(users); } );

4. 错误处理放在最后

app.use('/api', apiRoutes); // 404处理 app.use((req, res, next) => { res.status(404).json({ error: '未找到' }); }); // 错误处理 app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ error: '服务器错误' }); });

第三方中间件推荐

常用中间件列表

// 安全相关 const helmet = require('helmet'); // 安全头部 const cors = require('cors'); // CORS const rateLimit = require('express-rate-limit'); // 限流 // 请求解析 const cookieParser = require('cookie-parser'); // Cookie const multer = require('multer'); // 文件上传 // 日志 const morgan = require('morgan'); // 日志 const winston = require('winston'); // 日志框架 // 验证 const Joi = require('joi'); // 数据验证 const express-validator = require('express-validator'); // 其他 const compression = require('compression'); // 响应压缩 const responseTime = require('response-time'); // 响应时间

总结

Express中间件是其强大功能的基石,理解中间件的工作原理和开发方法,对于构建可维护、可扩展的Express应用至关重要。通过合理使用内置中间件、开发自定义中间件和集成第三方中间件,可以构建功能完善的Web应用。记住中间件的执行顺序、错误处理和最佳实践,将帮助你写出更优雅的代码。


发布者: 作者: 转发
评论区 (0)
U