Search K
Appearance
Appearance
📊 SEO元描述:2024年最新Express框架入门教程,详解Express安装配置、路由系统、中间件概念。包含完整项目示例,适合Node.js开发者快速掌握Express框架开发。
核心关键词:Express框架2024、Node.js Express入门、Express路由系统、Express中间件、Node.js Web框架
长尾关键词:Express框架怎么使用、Express安装配置方法、Express路由详解、Express中间件概念、Node.js Web开发框架
通过本节Express框架入门教程,你将系统性掌握:
Express框架是什么?这是Node.js开发者最关心的问题。Express是基于Node.js的快速、开放、极简的Web应用框架,也是Node.js生态系统中最受欢迎的Web框架。
💡 设计理念:Express遵循"不做决定"的哲学,给开发者最大的自由度来构建应用
让我们从Express的安装和第一个应用开始:
// 🎉 Express安装和基本使用
// 1. 初始化项目
// npm init -y
// npm install express
// 2. 创建基本的Express应用
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
// 基础路由
app.get('/', (req, res) => {
res.send(`
<h1>欢迎使用Express框架!</h1>
<p>这是你的第一个Express应用</p>
<ul>
<li><a href="/about">关于页面</a></li>
<li><a href="/api/users">用户API</a></li>
<li><a href="/api/health">健康检查</a></li>
</ul>
`);
});
// 关于页面
app.get('/about', (req, res) => {
res.json({
name: 'Express入门应用',
version: '1.0.0',
description: '学习Express框架的示例应用',
author: 'Node.js开发者',
features: [
'路由系统',
'中间件支持',
'JSON API',
'静态文件服务'
]
});
});
// API路由
app.get('/api/health', (req, res) => {
res.json({
status: 'OK',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
memory: process.memoryUsage()
});
});
// 启动服务器
app.listen(PORT, () => {
console.log(`Express服务器启动成功!`);
console.log(`访问地址: http://localhost:${PORT}`);
console.log(`环境: ${process.env.NODE_ENV || 'development'}`);
});// 📁 标准Express项目结构示例
// package.json
{
"name": "express-app",
"version": "1.0.0",
"description": "Express应用示例",
"main": "app.js",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"helmet": "^7.0.0",
"morgan": "^1.10.0"
},
"devDependencies": {
"nodemon": "^3.0.1",
"jest": "^29.0.0"
}
}
// app.js - 主应用文件
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const app = express();
// 中间件配置
app.use(helmet()); // 安全头
app.use(cors()); // 跨域支持
app.use(morgan('combined')); // 日志记录
app.use(express.json()); // JSON解析
app.use(express.urlencoded({ extended: true })); // URL编码解析
// 静态文件服务
app.use(express.static('public'));
// 路由配置
app.use('/api/users', require('./routes/users'));
app.use('/api/posts', require('./routes/posts'));
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
error: 'Internal Server Error',
message: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong!'
});
});
// 404处理
app.use('*', (req, res) => {
res.status(404).json({
error: 'Not Found',
message: `Route ${req.originalUrl} not found`
});
});
module.exports = app;
// server.js - 服务器启动文件
const app = require('./app');
const PORT = process.env.PORT || 3000;
const server = app.listen(PORT, () => {
console.log(`服务器运行在端口 ${PORT}`);
});
// 优雅关闭
process.on('SIGTERM', () => {
console.log('收到SIGTERM信号,正在关闭服务器...');
server.close(() => {
console.log('服务器已关闭');
process.exit(0);
});
});// 🚀 Express路由系统详解
const express = require('express');
const router = express.Router();
// 1. 基础路由
router.get('/', (req, res) => {
res.json({ message: '用户列表' });
});
// 2. 路径参数
router.get('/:id', (req, res) => {
const userId = req.params.id;
// 参数验证
if (!/^\d+$/.test(userId)) {
return res.status(400).json({
error: 'Invalid user ID',
message: '用户ID必须是数字'
});
}
res.json({
message: '获取用户信息',
userId: parseInt(userId),
user: {
id: parseInt(userId),
name: `用户${userId}`,
email: `user${userId}@example.com`
}
});
});
// 3. 多个路径参数
router.get('/:userId/posts/:postId', (req, res) => {
const { userId, postId } = req.params;
res.json({
message: '获取用户文章',
userId: parseInt(userId),
postId: parseInt(postId),
post: {
id: parseInt(postId),
title: `用户${userId}的文章${postId}`,
content: '文章内容...',
authorId: parseInt(userId)
}
});
});
// 4. 查询参数处理
router.get('/', (req, res) => {
const {
page = 1,
limit = 10,
sort = 'id',
order = 'asc',
search = ''
} = req.query;
// 参数验证和转换
const pageNum = Math.max(1, parseInt(page));
const limitNum = Math.min(100, Math.max(1, parseInt(limit)));
// 模拟数据
const users = Array.from({ length: 50 }, (_, i) => ({
id: i + 1,
name: `用户${i + 1}`,
email: `user${i + 1}@example.com`,
createdAt: new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000)
}));
// 搜索过滤
let filteredUsers = users;
if (search) {
filteredUsers = users.filter(user =>
user.name.includes(search) || user.email.includes(search)
);
}
// 排序
filteredUsers.sort((a, b) => {
const aVal = a[sort];
const bVal = b[sort];
const comparison = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
return order === 'desc' ? -comparison : comparison;
});
// 分页
const startIndex = (pageNum - 1) * limitNum;
const endIndex = startIndex + limitNum;
const paginatedUsers = filteredUsers.slice(startIndex, endIndex);
res.json({
data: paginatedUsers,
pagination: {
page: pageNum,
limit: limitNum,
total: filteredUsers.length,
totalPages: Math.ceil(filteredUsers.length / limitNum),
hasNext: endIndex < filteredUsers.length,
hasPrev: pageNum > 1
},
filters: {
search,
sort,
order
}
});
});
// 5. 路由参数验证中间件
function validateUserId(req, res, next) {
const userId = req.params.id || req.params.userId;
if (!userId || !/^\d+$/.test(userId)) {
return res.status(400).json({
error: 'Invalid User ID',
message: '用户ID必须是正整数'
});
}
// 将验证后的ID添加到请求对象
req.validatedUserId = parseInt(userId);
next();
}
// 使用验证中间件
router.get('/:id', validateUserId, (req, res) => {
const userId = req.validatedUserId;
res.json({
message: '获取用户信息',
userId,
user: {
id: userId,
name: `用户${userId}`,
email: `user${userId}@example.com`,
profile: {
bio: `这是用户${userId}的个人简介`,
location: '北京',
website: `https://user${userId}.example.com`
}
}
});
});
// 6. 路由组织和模块化
const userRoutes = express.Router();
const adminRoutes = express.Router();
// 用户相关路由
userRoutes.get('/profile', (req, res) => {
res.json({ message: '用户个人资料' });
});
userRoutes.put('/profile', (req, res) => {
res.json({ message: '更新用户资料' });
});
// 管理员路由
adminRoutes.get('/dashboard', (req, res) => {
res.json({ message: '管理员仪表板' });
});
adminRoutes.get('/users', (req, res) => {
res.json({ message: '管理员用户列表' });
});
// 挂载子路由
router.use('/user', userRoutes);
router.use('/admin', adminRoutes);
module.exports = router;Express路由系统要点:
// 💡 Express中间件概念详解
const express = require('express');
const app = express();
// 1. 应用级中间件 - 对所有路由生效
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
req.requestTime = Date.now();
next(); // 调用next()继续执行下一个中间件
});
// 2. 路径特定中间件
app.use('/api', (req, res, next) => {
console.log('API路由中间件');
req.isApiRequest = true;
next();
});
// 3. 内置中间件
app.use(express.json()); // 解析JSON请求体
app.use(express.urlencoded({ extended: true })); // 解析URL编码数据
app.use(express.static('public')); // 静态文件服务
// 4. 第三方中间件示例
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
app.use(helmet()); // 安全头
app.use(cors({
origin: ['http://localhost:3000', 'https://myapp.com'],
credentials: true
}));
app.use(morgan('combined')); // 访问日志
// 5. 自定义中间件函数
function requestLogger(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();
}
function authMiddleware(req, res, next) {
const token = req.headers.authorization;
if (!token) {
return res.status(401).json({
error: 'Unauthorized',
message: '缺少认证令牌'
});
}
// 简单的token验证(实际应用中应该更复杂)
if (token === 'Bearer valid-token') {
req.user = {
id: 1,
name: '认证用户',
role: 'user'
};
next();
} else {
res.status(401).json({
error: 'Unauthorized',
message: '无效的认证令牌'
});
}
}
function adminMiddleware(req, res, next) {
if (!req.user || req.user.role !== 'admin') {
return res.status(403).json({
error: 'Forbidden',
message: '需要管理员权限'
});
}
next();
}
// 使用自定义中间件
app.use(requestLogger);
// 6. 路由级中间件
app.get('/public', (req, res) => {
res.json({
message: '公开接口',
timestamp: new Date().toISOString(),
requestTime: req.requestTime
});
});
app.get('/protected', authMiddleware, (req, res) => {
res.json({
message: '受保护的接口',
user: req.user,
timestamp: new Date().toISOString()
});
});
app.get('/admin', authMiddleware, adminMiddleware, (req, res) => {
res.json({
message: '管理员接口',
user: req.user,
timestamp: new Date().toISOString()
});
});
// 7. 错误处理中间件(必须有4个参数)
app.use((err, req, res, next) => {
console.error('错误详情:', err);
// 根据错误类型返回不同响应
if (err.type === 'entity.parse.failed') {
return res.status(400).json({
error: 'Bad Request',
message: 'JSON格式错误'
});
}
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(413).json({
error: 'Payload Too Large',
message: '文件大小超过限制'
});
}
// 默认错误响应
res.status(500).json({
error: 'Internal Server Error',
message: process.env.NODE_ENV === 'development' ? err.message : '服务器内部错误'
});
});
// 8. 中间件执行顺序演示
app.get('/middleware-demo',
(req, res, next) => {
console.log('中间件1');
req.step1 = '完成';
next();
},
(req, res, next) => {
console.log('中间件2');
req.step2 = '完成';
next();
},
(req, res, next) => {
console.log('中间件3');
req.step3 = '完成';
next();
},
(req, res) => {
console.log('最终处理器');
res.json({
message: '中间件执行顺序演示',
steps: {
step1: req.step1,
step2: req.step2,
step3: req.step3
}
});
}
);
// 启动服务器
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Express中间件演示服务器启动:http://localhost:${PORT}`);
console.log('测试路由:');
console.log('- GET /public (公开接口)');
console.log('- GET /protected (需要认证,使用 Authorization: Bearer valid-token)');
console.log('- GET /admin (需要管理员权限)');
console.log('- GET /middleware-demo (中间件执行顺序)');
});通过本节Express框架入门教程的学习,你已经掌握:
A: Express基于Node.js HTTP模块构建,提供了更高级的抽象:1)简化的路由定义;2)强大的中间件系统;3)丰富的请求/响应API;4)更好的错误处理机制。Express让Web开发更加高效和结构化。
A: 中间件按定义顺序执行,顺序错误可能导致功能失效。例如:1)body-parser必须在路由处理前;2)认证中间件应在需要认证的路由前;3)错误处理中间件应在最后;4)静态文件中间件通常放在前面。
A: 选择标准:1)功能匹配度;2)维护活跃度;3)社区支持;4)性能表现;5)安全性。推荐使用官方推荐的中间件,如helmet(安全)、cors(跨域)、morgan(日志)等。
A: 优化策略:1)使用压缩中间件;2)启用HTTP缓存;3)优化数据库查询;4)使用连接池;5)实现负载均衡;6)监控和分析性能指标;7)使用CDN加速静态资源。
A: 错误处理最佳实践:1)使用专门的错误处理中间件;2)区分操作错误和程序错误;3)记录详细的错误日志;4)向客户端返回适当的错误信息;5)实现优雅的错误恢复机制。
// 问题:中间件没有被执行
// 解决:检查中间件定义顺序和next()调用
// 错误示例
app.use('/api', (req, res, next) => {
console.log('API中间件');
// 忘记调用next()
});
// 正确示例
app.use('/api', (req, res, next) => {
console.log('API中间件');
next(); // 必须调用next()
});// 问题:无法获取路由参数
// 解决:检查路由定义和参数名称
// 错误示例
app.get('/users/:userId', (req, res) => {
const id = req.params.id; // 参数名不匹配
});
// 正确示例
app.get('/users/:userId', (req, res) => {
const userId = req.params.userId; // 参数名匹配
});// 问题:无法解析JSON请求体
// 解决:确保使用express.json()中间件
// 正确配置
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
// 错误处理
app.use((err, req, res, next) => {
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
return res.status(400).json({ error: 'Invalid JSON' });
}
next(err);
});"Express框架是Node.js Web开发的基石,掌握了Express的核心概念和使用方法,你就具备了构建现代Web应用的重要技能。继续深入学习中间件和模板引擎,向全栈开发专家的目标迈进!"