一、Express 是什么
Express 是 Node.js 最流行的 Web 应用框架,提供了一套简洁灵活的 API 用于构建 Web 服务器和 RESTful API。它是 Node.js 后端开发的入门标准。
为什么需要 Express
Node.js 原生 http 模块可以直接创建服务器,但处理路由、中间件、请求解析等工作需要大量手写代码:
1 2 3 4 5 6 7
| const http = require('http'); http.createServer((req, res) => { if (req.url === '/api/users' && req.method === 'GET') { } });
|
Express 将上述重复工作抽象为简洁的 API:
1 2 3
| const express = require('express'); const app = express(); app.get('/api/users', (req, res) => res.json(users));
|
二、快速开始
1 2
| npm init -y npm install express
|
1 2 3 4 5 6 7 8 9 10 11
| const express = require('express'); const app = express(); const port = 3000;
app.get('/', (req, res) => { res.send('Hello Express'); });
app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });
|
三、路由
基础路由
1 2 3 4 5 6 7 8 9 10
| app.get('/users', (req, res) => res.send('GET /users')); app.post('/users', (req, res) => res.send('POST /users')); app.put('/users/:id', (req, res) => res.send(`PUT /users/${req.params.id}`)); app.delete('/users/:id', (req, res) => res.send(`DELETE /users/${req.params.id}`));
app.all('/api/*', (req, res, next) => { console.log(`${req.method} ${req.path}`); next(); });
|
路由参数
1 2 3 4 5 6 7 8 9 10
| app.get('/users/:userId/orders/:orderId', (req, res) => { console.log(req.params); });
app.get('/search', (req, res) => { console.log(req.query); });
|
路由模块化(Router)
1 2 3 4 5 6 7 8
| const router = express.Router();
router.get('/', (req, res) => { }); router.get('/:id', (req, res) => { }); router.post('/', (req, res) => { });
module.exports = router;
|
1 2 3
| const userRouter = require('./routes/users'); app.use('/api/users', userRouter);
|
四、中间件
中间件是 Express 的核心机制。它是一个函数,在请求处理流程中按顺序执行。
1 2 3 4 5
| function middleware(req, res, next) { }
|
应用级中间件
1 2 3 4 5 6 7 8 9 10 11
| app.use((req, res, next) => { console.log(`${new Date().toISOString()} ${req.method} ${req.path}`); next(); });
app.use('/api', (req, res, next) => { req.apiRequest = true; next(); });
|
内置中间件
1 2 3 4 5 6 7 8 9
| app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));
|
第三方中间件
1
| npm install cors morgan helmet
|
1 2 3 4 5 6 7
| const cors = require('cors'); const morgan = require('morgan'); const helmet = require('helmet');
app.use(helmet()); app.use(cors()); app.use(morgan('combined'));
|
错误处理中间件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| app.get('/error', (req, res) => { throw new Error('something broke'); });
app.get('/async-error', (req, res, next) => { asyncOperation().catch(next); });
app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ message: err.message, ...(process.env.NODE_ENV === 'development' && { stack: err.stack }), }); });
|
五、请求与响应
Request 对象
1 2 3 4 5 6 7 8 9
| app.post('/users', (req, res) => { req.body; req.query; req.params; req.headers; req.ip; req.path; req.method; });
|
Response 对象
1 2 3 4 5 6
| res.status(201); res.json({ id: 1, name: 'Alice' }); res.send('<h1>Hello</h1>'); res.redirect('/login'); res.sendFile('/path/to/file.pdf'); res.download('/path/to/file.pdf');
|
链式调用
1
| res.status(201).json({ id: 1 });
|
六、静态文件
1 2 3 4 5 6 7 8 9 10
| app.use(express.static('public'));
app.use(express.static('public')); app.use(express.static('uploads'));
app.use('/static', express.static('public'));
|
七、模板引擎
Express 支持多种模板引擎(EJS、Pug、Handlebars)。
1 2 3 4 5 6 7
| app.set('view engine', 'ejs'); app.set('views', './views');
app.get('/profile', (req, res) => { res.render('profile', { name: 'Alice', age: 25 }); });
|
1 2 3
| <h1><%= name %></h1> <p>Age: <%= age %></p>
|
八、项目结构规范
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| project/ ├── app.js # 入口文件 ├── routes/ # 路由 │ ├── users.js │ └── orders.js ├── controllers/ # 控制器(处理业务逻辑) │ ├── userController.js │ └── orderController.js ├── models/ # 数据模型 │ └── user.js ├── middleware/ # 自定义中间件 │ ├── auth.js │ └── validate.js ├── config/ # 配置 │ └── index.js ├── public/ # 静态文件 │ ├── css/ │ └── js/ └── views/ # 模板 └── index.ejs
|
控制器模式
1 2 3 4 5 6 7 8 9
| exports.list = async (req, res, next) => { try { const users = await User.find(); res.json(users); } catch (err) { next(err); } };
|
1 2 3 4 5 6 7
| const router = require('express').Router(); const userCtrl = require('../controllers/userController');
router.get('/', userCtrl.list); router.get('/:id', userCtrl.getById); router.post('/', userCtrl.create);
|
九、常见问题
Q1: req.body 始终为 undefined
1 2
| app.use(express.json());
|
Q2: 跨域问题
1 2 3 4 5 6 7 8
| const cors = require('cors'); app.use(cors());
app.use(cors({ origin: 'https://example.com', methods: ['GET', 'POST'], }));
|
Q3: 异步错误捕获
1 2 3 4 5 6 7 8
| app.get('/async', (req, res, next) => { asyncFunction().catch(next); });
const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
|
Q4: Express vs Koa 怎么选
Express 社区更成熟、中间件生态丰富、学习曲线低。Koa 利用 async/await 更优雅地处理异步,但社区较小。大多数新项目仍首选 Express。
十、推荐学习路径
- 掌握基础路由和中间件机制
- 使用 express.Router 模块化路由
- 集成数据库(Mongoose / Sequelize)
- 实现 JWT 鉴权和错误处理
- 使用 cors、helmet、morgan 等中间件加固生产环境
- 结合 Docker 和 PM2 部署