node.js 中的 express 框架基础到进阶指南
一、基础篇:Express 核心概念入门
1. 第一个 Express 应用:极简启动
先看一个最基础的 Express 应用,理解其核心结构:
// 引入 Express 模块
const express = require('express');
// 创建 Express 应用实例
const app = express();
// 定义端口
const PORT = 3000;
// 定义根路由:处理 GET 请求
app.get('/', (req, res) => {
res.send('Hello Express!');
});
// 启动服务器监听端口
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});核心解析:
express():创建一个 Express 应用实例,封装了 HTTP 服务器的创建和请求处理逻辑。app.get(path, handler):定义路由,监听path路径的 GET 请求,handler是请求处理函数,接收req(请求对象)和res(响应对象)。res.send():发送响应内容,自动设置Content-Type(字符串默认text/html,对象默认application/json)。
2. 路由(Routing):请求的“导航系统”
路由是 Express 处理请求的核心,负责将不同的 HTTP 请求(方法+路径)映射到对应的处理函数。
(1)基本路由:支持所有 HTTP 方法
// GET 请求:获取数据
app.get('/users', (req, res) => {
res.json({ users: ['Alice', 'Bob'] });
});
// POST 请求:创建数据
app.post('/users', (req, res) => {
res.status(201).json({ message: 'User created' });
});
// PUT 请求:更新数据(完整替换)
app.put('/users/:id', (req, res) => {
res.json({ message: `User ${req.params.id} updated` });
});
// DELETE 请求:删除数据
app.delete('/users/:id', (req, res) => {
res.json({ message: `User ${req.params.id} deleted` });
});(2)路由参数与查询字符串
- 路由参数:通过
:name定义,存储在req.params中(如/users/:id匹配/users/123,req.params.id = '123')。 - 查询字符串:URL 中
?后的参数,存储在req.query中(如/users?page=1&limit=10,req.query = { page: '1', limit: '10' })。
app.get('/users/:id/posts', (req, res) => {
const { id } = req.params;
const { page = 1, limit = 10 } = req.query;
res.json({ userId: id, page, limit });
});
(3)路由模块化:用express.Router()拆分代码
当路由增多时,将所有路由写在一个文件中会导致代码臃肿。使用 Router 可以将路由按模块拆分:
// routes/users.js:用户模块路由
const express = require('express');
const router = express.Router();
// 注意:路径是相对于挂载点的(这里的 '/' 对应 '/users')
router.get('/', (req, res) => res.json({ users: [] }));
router.get('/:id', (req, res) => res.json({ user: req.params.id }));
module.exports = router;// app.js:主文件中挂载路由
const userRouter = require('./routes/users');
// 将 userRouter 挂载到 '/users' 路径下
app.use('/users', userRouter);
(4)路由链:简化同一资源的多个路由
对于同一资源(如 /users)的多个 HTTP 方法,可以用 app.route() 链式调用:
app.route('/users')
.get((req, res) => res.json({ users: [] }))
.post((req, res) => res.status(201).json({ message: 'Created' }));
3. 中间件(Middleware):Express 的“灵魂”
中间件是 Express 最核心的设计理念——它是一个函数,在请求-响应周期中被调用,可以访问 req、res 和 next(下一个中间件函数)。中间件可以执行任何代码、修改请求/响应对象、结束请求-响应周期,或调用下一个中间件。
(1)中间件的分类与用法
- 应用级中间件:绑定到
app实例,对所有请求生效(或指定路径生效)。 - 路由级中间件:绑定到
express.Router()实例,仅对该路由模块生效。 - 错误处理中间件:专门处理错误,有 4 个参数
(err, req, res, next)。 - 内置中间件:Express 自带的中间件(如
express.json、express.static)。 - 第三方中间件:社区开发的中间件(如
morgan、cors)。
(2)内置中间件:最常用的两个
express.json():解析请求体中的 JSON 数据(存储到req.body)。express.urlencoded():解析 URL 编码的请求体(如表单提交,存储到req.body)。express.static():托管静态文件(如 HTML、CSS、图片)。
// 解析 JSON 请求体(必须放在路由之前)
app.use(express.json());
// 解析 URL 编码请求体(extended: false 表示使用 querystring 库解析)
app.use(express.urlencoded({ extended: false }));
// 托管 public 目录下的静态文件(访问 /css/style.css 对应 public/css/style.css)
app.use(express.static('public'));
(3)自定义应用级中间件
// 全局中间件:每个请求都会执行
app.use((req, res, next) => {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
next(); // 调用下一个中间件,否则请求会挂起
});
// 路径特定中间件:仅对 /api 路径下的请求生效
app.use('/api', (req, res, next) => {
console.log('Accessing API');
next();
});(4)错误处理中间件
错误处理中间件必须有 4 个参数,且要放在所有中间件和路由之后:
// 模拟一个错误路由
app.get('/error', (req, res, next) => {
const error = new Error('Something went wrong!');
error.status = 500;
next(error); // 将错误传递给错误处理中间件
});
// 错误处理中间件
app.use((err, req, res, next) => {
const status = err.status || 500;
const message = err.message || 'Internal Server Error';
res.status(status).json({ error: message });
});二、进阶篇:构建生产级应用
1. 统一错误处理:优雅处理同步与异步错误
Express 4.x 默认不会捕获异步代码中的错误(如 async/await 中的 throw),需要手动包装或使用工具。
(1)自定义错误类
先定义一个统一的错误类,方便传递状态码和错误信息:
class AppError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
this.isOperational = true; // 标记为可预期的业务错误(非系统错误)
Error.captureStackTrace(this, this.constructor);
}
}
(2)异步错误包装器
用一个高阶函数包装异步路由,自动捕获错误并传递给错误处理中间件:
const asyncWrapper = (fn) => {
return (req, res, next) => {
fn(req, res, next).catch(next); // 捕获异步错误,传递给 next(err)
};
};
(3)完整示例
// 路由中使用
app.get('/users/:id', asyncWrapper(async (req, res, next) => {
const user = await User.findById(req.params.id); // 模拟异步数据库查询
if (!user) {
throw new AppError('User not found', 404); // 抛出业务错误
}
res.json({ user });
}));
// 错误处理中间件(区分业务错误和系统错误)
app.use((err, req, res, next) => {
const { statusCode = 500, message, isOperational } = err;
res.status(statusCode).json({
error: isOperational ? message : 'Internal Server Error',
...(process.env.NODE_ENV === 'development' && { stack: err.stack }) // 开发环境返回堆栈
});
});2. RESTful API 设计实践
Express 非常适合构建 RESTful API,核心原则是“资源导向”,用 HTTP 方法表示操作类型。
(1)资源命名与 HTTP 方法对应
| 资源 | GET(获取) | POST(创建) | PUT(完整更新) | PATCH(部分更新) | DELETE(删除) |
|---|---|---|---|---|---|
| /users | 获取所有用户 | 创建新用户 | 批量更新用户(不推荐) | 批量部分更新(不推荐) | 删除所有用户(不推荐) |
| /users/:id | 获取指定 ID 的用户 | 不允许 | 替换指定 ID 的用户 | 部分更新指定 ID 的用户 | 删除指定 ID 的用户 |
(2)示例:用户管理 API
// 模拟用户数据
let users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
// 获取所有用户(支持分页)
app.get('/users', asyncWrapper(async (req, res) => {
const { page = 1, limit = 10 } = req.query;
const start = (page - 1) * limit;
const end = start + parseInt(limit);
const paginatedUsers = users.slice(start, end);
res.json({
data: paginatedUsers,
page: parseInt(page),
limit: parseInt(limit),
total: users.length
});
}));
// 创建用户
app.post('/users', asyncWrapper(async (req, res, next) => {
const { name, email } = req.body;
if (!name || !email) {
throw new AppError('Name and email are required', 400);
}
const newUser = { id: users.length + 1, name, email };
users.push(newUser);
res.status(201).json({ data: newUser });
}));3. 文件上传:Multer 中间件
Express 本身不支持文件上传,需要使用第三方中间件 multer。
(1)安装与基本配置
npm install multer
const multer = require('multer');
// 配置存储:指定文件存储路径和文件名
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/'); // 存储到 uploads 目录(需提前创建)
},
filename: (req, file, cb) => {
// 生成唯一文件名:时间戳 + 原始文件名
const uniqueName = `${Date.now()}-${file.originalname}`;
cb(null, uniqueName);
}
});
// 配置文件过滤器:只允许图片上传
const fileFilter = (req, file, cb) => {
if (file.mimetype.startsWith('image/')) {
cb(null, true); // 允许上传
} else {
cb(new AppError('Only images are allowed', 400), false); // 拒绝上传
}
};
// 初始化 Multer
const upload = multer({
storage,
fileFilter,
limits: { fileSize: 5 * 1024 * 1024 } // 限制文件大小 5MB
});(2)单文件与多文件上传
// 单文件上传:字段名为 avatar
app.post('/upload/avatar', upload.single('avatar'), (req, res) => {
res.json({
message: 'Avatar uploaded successfully',
file: req.file // 上传的文件信息(路径、大小等)
});
});
// 多文件上传:字段名为 photos,最多 5 个
app.post('/upload/photos', upload.array('photos', 5), (req, res) => {
res.json({
message: 'Photos uploaded successfully',
files: req.files // 上传的文件数组
});
});4. 安全最佳实践
生产环境中必须关注安全,以下是 Express 应用的核心安全措施:
(1)Helmet:设置安全 HTTP 头
helmet 是一个安全中间件,通过设置各种 HTTP 头来防止常见的 Web 攻击(如 XSS、点击劫持)。
npm install helmet
const helmet = require('helmet');
app.use(helmet()); // 启用所有默认安全头
(2)CORS:配置跨域资源共享
如果 API 被前端跨域调用,需要配置 cors 中间件。
npm install cors
const cors = require('cors');
// 允许所有来源(开发环境用)
app.use(cors());
// 或仅允许特定来源(生产环境用)
app.use(cors({
origin: 'https://your-frontend.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
(3)速率限制:防止暴力攻击
用 express-rate-limit 限制同一 IP 的请求频率。
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
// 全局速率限制:15 分钟内最多 100 个请求
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests, please try again later'
});
app.use(globalLimiter);
// 登录接口单独限制:15 分钟内最多 5 个请求
const loginLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5,
message: 'Too many login attempts, please try again later'
});
app.post('/login', loginLimiter, (req, res) => {
res.json({ message: 'Login successful' });
});(4)输入验证:防止恶意数据
用 joi 或 express-validator 验证请求参数和请求体。
npm install joi
const Joi = require('joi');
// 定义用户创建的验证 schema
const userSchema = Joi.object({
name: Joi.string().min(2).max(30).required(),
email: Joi.string().email().required(),
age: Joi.number().integer().min(18).max(100)
});
// 在路由中使用
app.post('/users', (req, res, next) => {
const { error } = userSchema.validate(req.body);
if (error) {
throw new AppError(error.details[0].message, 400);
}
next(); // 验证通过,继续处理
}, (req, res) => {
res.json({ message: 'User created' });
});5. 性能优化
生产环境中需要关注性能,以下是几个核心优化点:
(1)压缩响应:使用compression中间件
npm install compression
const compression = require('compression');
app.use(compression()); // 压缩所有响应(放在路由之前)
(2)静态文件缓存
给静态文件设置 maxAge,让浏览器缓存:
app.use(express.static('public', {
maxAge: '1d' // 缓存 1 天
}));
(3)避免同步操作
所有 I/O 操作(数据库、文件系统)都使用异步方式,避免阻塞事件循环。
到此这篇关于node.js 中的 express 框架基础到进阶指南的文章就介绍到这了,更多相关node.js express 框架内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Node.js使用mysql2 库批量更新(Bulk Update)多条数据的方案
文章介绍了在Node.js中使用mysql2库批量更新多条数据的三种方法:使用CASEWHEN语句、INSERT...ONDUPLICATEKEYUPDATE和事务+循环更新,每种方法都有其适用场景和优缺点,建议根据数据量和更新逻辑选择合适的方法,感兴趣的朋友跟随小编一起看看吧2026-01-01


最新评论