Express框架完全指南
1. Express框架概述
Express是一个基于Node.js平台的Web应用开发框架,由TJ Holowaychuk于2010年创建。它提供了一系列强大特性帮助你创建各种Web和移动设备应用。Express被称为"Node.js的瑞士军刀",是Node.js生态系统中最流行的Web框架之一。
1.1 核心特点
- 轻量级:仅提供必要的功能,无冗余代码
- 灵活:不强制使用特定的模板引擎或ORM
- 高性能:基于Node.js的非阻塞I/O模型
- 丰富的中间件生态:通过中间件扩展功能
- 简洁而灵活的路由系统:便于定义应用的端点
- 高效的中间件机制:可扩展性强
- 丰富的HTTP工具:简化请求和响应处理
- 模板引擎支持:便于渲染动态内容
- 易于集成数据库:可与多种数据库无缝集成
- 社区活跃:拥有庞大的社区和丰富的资源
1.2 设计哲学
Express的核心philosophy是"少即是多",提供基础功能而不限制开发者的选择。它建立在Node.js的HTTP模块之上,通过添加路由、中间件和错误处理等功能,使Web开发更加高效和便捷。
2. 安装与配置
2.1 前提条件
在开始使用Express之前,确保你已经安装了:
- Node.js(推荐LTS版本)
- npm(Node.js包管理器)
2.2 安装Express
首先创建一个新的项目目录,然后初始化npm:
mkdir my-express-app
cd my-express-app
npm init -y
然后安装Express:
npm install express --save
2.3 创建第一个Express应用
创建一个名为app.js的文件,添加以下代码:
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
运行应用:
node app.js
打开浏览器访问 http://localhost:3000,你将看到 "Hello World!" 消息。
3. 基本概念
3.1 应用程序对象
app 对象是Express的实例,它是整个应用的核心:
const app = express()
应用程序对象负责:
- 定义路由
- 配置中间件
- 设置视图引擎
- 启动HTTP服务器
3.2 路由
路由决定了应用程序如何响应客户端对特定端点的请求,包含一个URL路径和一个HTTP方法。
基本路由格式:
app.METHOD(PATH, HANDLER)
其中:
app是Express实例METHOD是HTTP请求方法(get, post, put, delete等)PATH是服务器上的路径HANDLER是当路由匹配时执行的函数
3.3 请求和响应对象
路由处理函数接收两个主要对象:
req(请求对象):包含客户端请求的信息res(响应对象):用于向客户端发送响应
常用的请求对象属性:
req.url:请求URLreq.method:请求方法req.headers:请求头req.body:请求体数据(需要body-parser中间件)req.params:URL参数req.query:查询字符串参数req.cookies:Cookie(需要cookie-parser中间件)
常用的响应对象方法:
res.send():发送响应res.json():发送JSON响应res.status():设置HTTP状态码res.setHeader():设置响应头res.redirect():重定向res.render():渲染视图模板
4. 中间件机制
Express.js的核心是中间件(Middleware)机制:
- 中间件是一个函数,可以访问请求对象(req)、响应对象(res)和应用的请求-响应循环中的下一个中间件函数(next)
- 中间件可以执行任何操作,修改请求和响应对象,结束请求-响应循环,或调用下一个中间件
- 中间件按照定义的顺序执行
4.1 中间件类型
4.1.1 应用级中间件
绑定到应用程序实例的中间件:
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
4.1.2 路由级中间件
绑定到路由对象的中间件:
const router = express.Router()
router.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
4.1.3 错误处理中间件
处理请求过程中发生的错误的中间件:
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
4.1.4 内置中间件
Express.js提供的内置中间件:
app.use(express.json()); // 解析JSON请求体
app.use(express.urlencoded({ extended: true })); // 解析URL编码的请求体
app.use(express.static('public')); // 提供静态文件
4.1.5 第三方中间件
通过NPM安装的中间件:
const cookieParser = require('cookie-parser');
app.use(cookieParser());
4.2 执行流程
请求处理的典型流程:
请求 -> 应用级中间件 -> 路由级中间件 -> 路由处理函数 -> 响应
| |
v v
错误处理中间件 <- 错误处理中间件
5. 路由系统
5.1 路由原理
Express.js的路由系统基于路径和HTTP方法进行匹配:
- 当请求到达服务器时,Express会根据请求的URL和方法查找匹配的路由处理函数
- 路由可以包含路径参数、查询字符串等
- 路由处理函数负责生成响应
5.2 路由匹配规则
- 精确路径匹配:
app.get('/users', ...)匹配/users - 路径参数:
app.get('/users/:id', ...)匹配/users/123 - 通配符:
app.get('/users/*', ...)匹配/users/下的所有路径 - 正则表达式:
app.get(/^/users/d+$/, ...)匹配/users/后跟随数字的路径
5.3 基本路由示例
// 处理GET请求
app.get('/', (req, res) => {
res.send('Hello World!')
})
// 处理POST请求
app.post('/users', (req, res) => {
res.status(201).send('User created')
})
// 处理带参数的请求
app.get('/users/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`)
})
// 处理所有HTTP方法
app.all('/secret', (req, res, next) => {
console.log('Accessing the secret section...')
next() // 传递控制权给下一个处理函数
})
6. 静态文件服务
Express提供了内置的中间件来提供静态文件,如图片、CSS文件和JavaScript文件:
app.use(express.static('public'))
这会使public目录中的文件可以通过URL直接访问。例如,如果public目录中有一个images子目录,其中包含一个logo.png文件,那么可以通过http://localhost:3000/images/logo.png访问该文件。
你也可以为静态文件服务指定前缀:
app.use('/static', express.static('public'))
这样,文件将通过http://localhost:3000/static/images/logo.png访问。
7. 核心对象详解
7.1 请求对象(req)详解
请求对象包含HTTP请求的所有信息:
req.url:请求URLreq.method:请求方法req.headers:请求头req.body:请求体(需要body-parser中间件)req.params:路径参数req.query:查询字符串参数req.cookies:Cookie(需要cookie-parser中间件)req.ip:客户端IP地址req.originalUrl:原始请求URLreq.path:请求路径req.hostname:主机名req.protocol:协议(http或https)
7.2 响应对象(res)详解
响应对象用于发送HTTP响应:
res.send():发送响应res.json():发送JSON响应res.status():设置HTTP状态码res.setHeader():设置响应头res.redirect():重定向res.render():渲染模板(需要模板引擎)res.sendFile():发送文件res.download():触发文件下载res.type():设置Content-Typeres.append():添加响应头res.cookie():设置Cookieres.clearCookie():清除Cookie
8. 实用示例
8.1 基本Express应用
// app.js
const express = require('express');
const app = express();
const port = 3000;
// 应用级中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 路由定义
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.get('/users', (req, res) => {
// 模拟用户数据
const users = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' }
];
res.json(users);
});
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
// 模拟根据ID查询用户
res.json({ id: userId, name: `User ${userId}` });
});
app.post('/users', (req, res) => {
const newUser = req.body;
// 模拟创建用户
res.status(201).json({ id: 3, ...newUser });
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// 启动服务器
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
8.2 路由模块化
// routes/users.js
const express = require('express');
const router = express.Router();
// 路由级中间件
router.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
router.get('/', (req, res) => {
res.json([{ id: 1, name: 'John Doe' }]);
});
router.get('/:id', (req, res) => {
res.json({ id: req.params.id, name: `User ${req.params.id}` });
});
module.exports = router;
// app.js
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);
8.3 中间件示例
// 日志中间件
const logger = (req, res, next) => {
console.log(`${req.method} ${req.url} - ${new Date().toISOString()}`);
next();
};
// 错误处理中间件
const errorHandler = (err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
};
app.use(logger);
// 其他路由...
app.use(errorHandler);
9. 练习项目
创建一个简单的Express应用,包含以下功能:
- 提供静态文件服务
- 实现几个基本路由
- 添加简单的中间件
10. 最佳实践
- 使用环境变量:存储配置信息,如端口号、数据库连接字符串等
- 模块化路由:将路由拆分为多个文件,提高可维护性
- 错误处理:使用错误处理中间件捕获和处理所有错误
- 日志记录:记录请求和响应信息,便于调试和监控
- 输入验证:验证所有用户输入,防止注入攻击
- 使用async/await:避免回调地狱
- 限制请求速率:防止DoS攻击
- 设置安全头部:使用helmet中间件增强安全性
- 代码风格一致:使用ESLint和Prettier保持代码风格一致
- 测试:编写单元测试和集成测试
11. 专业解决方案
11.1 路由模块化
- 使用
express.Router()创建模块化路由 - 将不同功能的路由分离到不同文件中
11.2 身份验证
- passport.js:灵活的身份验证中间件
- jsonwebtoken:基于JWT的身份验证
11.3 数据库集成
- mongoose:MongoDB的ODM
- sequelize:ORM框架,支持多种关系型数据库
11.4 视图引擎
- ejs:简单的模板引擎
- pug:优雅的模板引擎
11.5 测试
- mocha:JavaScript测试框架
- supertest:HTTP断言库,用于测试Express应用
11.6 性能优化
- 静态文件缓存
- 压缩响应数据
- 路由懒加载
- 使用CDN分发静态资源
12. 下一步学习
现在你已经了解了Express的基础知识,接下来可以深入学习:
- 路由系统详解
- 中间件高级应用
- 错误处理机制
- 模板引擎使用
- 数据库集成
- Express安全最佳实践
继续阅读后续章节,掌握更多Express高级功能!