一、Express 简介与环境准备
1.1 什么是 Express
- Express :基于 Node.js 的极简、灵活 Web 框架 ,封装 http 模块,专注路由+中间件,适合快速开发 Web 服务与 RESTful API。
- 特点:轻量、高性能、中间件生态强、路由灵活、无强依赖、社区成熟。
1.2 环境安装(必须先装 Node.js)
bash
# 1. 检查 Node 版本(≥14.x)
node -v
npm -v
# 2. 创建项目目录
mkdir express-demo && cd express-demo
# 3. 初始化 package.json(-y 全部默认)
npm init -y
# 4. 安装 Express(生产依赖)
npm install express
# 5. 可选:安装热更新工具(开发依赖)
npm install nodemon -D
1.3 第一个 Express 应用(Hello World)
新建 app.js:
javascript
// 1. 引入 express
const express = require('express');
// 2. 创建应用实例
const app = express();
// 3. 定义端口
const port = 3000;
// 4. 路由:GET 请求根路径
app.get('/', (req, res) => {
res.send('Hello Express! 🚀');
});
// 5. 启动服务器
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
运行:
bash
# 方式1:node 运行
node app.js
# 方式2:nodemon 热更新(改代码自动重启)
# package.json scripts 加:"dev": "nodemon app.js"
npm run dev
浏览器访问 http://localhost:3000,看到 Hello Express 即成功。
二、核心对象:req(请求)& res(响应)
2.1 req 对象(Request):获取客户端数据
javascript
app.get('/user/:id', (req, res) => {
// 1. 路径参数:/user/123 → id=123
console.log('路径参数:', req.params); // { id: '123' }
// 2. 查询参数:/search?q=express → q=express
console.log('查询参数:', req.query); // { q: 'express' }
// 3. 请求头
console.log('请求头:', req.headers);
// 4. 请求方法、URL、IP
console.log('方法:', req.method);
console.log('URL:', req.url);
console.log('IP:', req.ip);
res.send('req 信息查看控制台');
});
2.2 res 对象(Response):向客户端返回数据
常用方法:
javascript
app.get('/res', (req, res) => {
res.send('普通文本/HTML'); // 自动识别 Content-Type
res.json({ name: 'express' }); // 返回 JSON(常用)
res.status(200).json({ code: 200, data: '成功' }); // 链式调用
res.redirect('/'); // 重定向
res.sendFile(__dirname + '/public/index.html'); // 发送文件
res.render('index', { title: 'Express' }); // 渲染模板(需模板引擎)
});
三、路由系统(核心)
3.1 基础路由(HTTP 方法 + 路径 + 回调)
javascript
// GET:查询数据
app.get('/api/users', (req, res) => {
res.json([{ id: 1, name: '张三' }, { id: 2, name: '李四' }]);
});
// POST:创建数据
app.post('/api/users', (req, res) => {
res.status(201).json({ message: '创建成功' });
});
// PUT:更新数据
app.put('/api/users/:id', (req, res) => {
res.json({ message: `更新用户 ${req.params.id} 成功` });
});
// DELETE:删除数据
app.delete('/api/users/:id', (req, res) => {
res.json({ message: `删除用户 ${req.params.id} 成功` });
});
3.2 动态路由(路径参数)
javascript
// 匹配 /user/1、/user/abc 等
app.get('/user/:id', (req, res) => {
const userId = req.params.id;
res.send(`用户 ID:${userId}`);
});
// 多参数:/user/123/post/456
app.get('/user/:userId/post/:postId', (req, res) => {
res.json(req.params); // { userId: '123', postId: '456' }
});
3.3 路由模块化(项目必用,解耦)
- 新建
routes/user.js(子路由):
javascript
const express = require('express');
const router = express.Router(); // 创建路由实例
// 子路由:/api/users
router.get('/', (req, res) => {
res.send('用户列表');
});
router.get('/:id', (req, res) => {
res.send(`用户 ${req.params.id}`);
});
module.exports = router; // 导出路由
- 主文件
app.js引入:
javascript
const userRouter = require('./routes/user');
// 挂载路由:所有子路由前加 /api/users
app.use('/api/users', userRouter);
四、中间件(灵魂,洋葱模型)
4.1 中间件本质
函数 (req, res, next) => {} ,按 app.use() 顺序执行,next() 传递控制权。
4.2 分类与用法
1)内置中间件(无需安装)
javascript
// 解析 JSON 请求体(POST/PUT 常用)
app.use(express.json());
// 解析表单数据(application/x-www-form-urlencoded)
app.use(express.urlencoded({ extended: true }));
// 静态资源托管(访问 public 目录文件:http://localhost:3000/xxx.jpg)
const path = require('path');
app.use(express.static(path.join(__dirname, 'public')));
2)自定义中间件
javascript
// 日志中间件:记录请求时间、方法、URL
app.use((req, res, next) => {
console.log(`[${new Date().toLocaleString()}] ${req.method} ${req.url}`);
next(); // 必须调用,否则请求挂起
});
// 全局中间件:所有路由前执行
app.use((req, res, next) => {
console.log('全局中间件');
next();
});
3)第三方中间件(常用)
bash
# 安装
npm install cors morgan
javascript
// 跨域(解决前端跨域问题)
const cors = require('cors');
app.use(cors());
// 日志增强(比自定义更全)
const morgan = require('morgan');
app.use(morgan('dev'));
五、静态资源与模板引擎
5.1 静态资源托管
javascript
// public 目录放图片、CSS、JS 等
app.use(express.static('public'));
// 访问:http://localhost:3000/images/logo.png
5.2 模板引擎(服务端渲染,可选)
以 EJS 为例(简单易上手):
bash
# 安装
npm install ejs
javascript
// app.js 设置模板引擎
app.set('view engine', 'ejs');
// 模板文件目录:views
app.set('views', './views');
// 渲染模板
app.get('/ejs', (req, res) => {
res.render('index', { title: 'Express EJS', message: 'Hello EJS' });
});
新建 views/index.ejs:
html
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= message %></h1>
</body>
</html>
六、错误处理(必加,防止崩溃)
6.1 全局错误中间件(4 个参数:err, req, res, next)
javascript
// 路由中抛出错误
app.get('/error', (req, res, next) => {
const err = new Error('自定义错误');
err.status = 500;
next(err); // 传递给错误中间件
});
// 全局错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
code: err.status || 500,
message: err.message || '服务器错误'
});
});
七、RESTful API 实战(完整示例)
7.1 项目结构
express-demo/
├── app.js # 入口文件
├── package.json
├── routes/
│ └── user.js # 用户路由
└── public/ # 静态资源
7.2 完整代码
app.js:
javascript
const express = require('express');
const cors = require('cors');
const morgan = require('morgan');
const userRouter = require('./routes/user');
const app = express();
const port = 3000;
// 中间件
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// 路由
app.use('/api/users', userRouter);
// 根路由
app.get('/', (req, res) => {
res.send('Express RESTful API 服务运行中');
});
// 全局错误处理
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ message: '服务器错误' });
});
// 启动服务
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
routes/user.js:
javascript
const express = require('express');
const router = express.Router();
// 模拟数据
let users = [
{ id: 1, name: '张三', age: 20 },
{ id: 2, name: '李四', age: 25 }
];
// GET /api/users - 获取所有用户
router.get('/', (req, res) => {
res.json(users);
});
// GET /api/users/:id - 获取单个用户
router.get('/:id', (req, res) => {
const user = users.find(u => u.id === parseInt(req.params.id));
if (!user) return res.status(404).json({ message: '用户不存在' });
res.json(user);
});
// POST /api/users - 创建用户
router.post('/', (req, res) => {
if (!req.body.name || !req.body.age) {
return res.status(400).json({ message: '姓名和年龄必填' });
}
const newUser = {
id: users.length > 0 ? Math.max(...users.map(u => u.id)) + 1 : 1,
name: req.body.name,
age: req.body.age
};
users.push(newUser);
res.status(201).json(newUser);
});
// PUT /api/users/:id - 更新用户
router.put('/:id', (req, res) => {
const userIndex = users.findIndex(u => u.id === parseInt(req.params.id));
if (userIndex === -1) return res.status(404).json({ message: '用户不存在' });
users[userIndex] = { ...users[userIndex], ...req.body };
res.json(users[userIndex]);
});
// DELETE /api/users/:id - 删除用户
router.delete('/:id', (req, res) => {
const initialLength = users.length;
users = users.filter(u => u.id !== parseInt(req.params.id));
if (users.length === initialLength) return res.status(404).json({ message: '用户不存在' });
res.json({ message: '删除成功' });
});
module.exports = router;
八、高级特性(进阶必学)
8.1 异步路由(async/await)
Express 5 原生支持,Express 4 需配合 next():
javascript
// Express 4 异步处理
app.get('/async', async (req, res, next) => {
try {
const data = await fetchData(); // 异步操作
res.json(data);
} catch (err) {
next(err); // 错误传递给错误中间件
}
});
8.2 参数校验(joi 库)
bash
npm install joi
javascript
const Joi = require('joi');
app.post('/validate', (req, res) => {
const schema = Joi.object({
name: Joi.string().min(2).max(10).required(),
age: Joi.number().integer().min(18).required()
});
const { error } = schema.validate(req.body);
if (error) return res.status(400).json({ message: error.details[0].message });
res.json({ message: '校验通过' });
});
8.3 集成数据库(Mongoose + MongoDB)
bash
npm install mongoose
javascript
const mongoose = require('mongoose');
// 连接 MongoDB
mongoose.connect('mongodb://localhost:27017/express-db')
.then(() => console.log('MongoDB 连接成功'))
.catch(err => console.error('MongoDB 连接失败:', err));
// 定义用户模型
const userSchema = new mongoose.Schema({
name: String,
age: Number
});
const User = mongoose.model('User', userSchema);
// 路由使用
app.get('/db/users', async (req, res) => {
const users = await User.find();
res.json(users);
});
九、部署与性能优化
9.1 部署到服务器(PM2 守护进程)
bash
# 安装 PM2
npm install pm2 -g
# 启动应用
pm2 start app.js
# 查看进程
pm2 list
# 开机自启
pm2 startup
9.2 性能优化
- 使用 compression 压缩响应体
- 静态资源托管(CDN 加速)
- 数据库索引优化
- 异步操作避免阻塞事件循环
十、总结
- Express 核心:路由 + 中间件,极简灵活,生态丰富。
- 学习路径:环境搭建 → 基础路由 → 中间件 → 静态资源/模板引擎 → 错误处理 → RESTful 实战 → 数据库集成 → 部署优化。
- 适合场景:中小型 Web 服务、RESTful API、后端渲染网站。