Appearance
路由管理
什么是路由
路由是指确定应用如何响应客户端对特定端点的请求,这些端点由 URI(或路径)和 HTTP 请求方法(GET、POST、PUT、DELETE 等)组成。路由定义了应用的 API 结构,是 Web 应用的核心组成部分。
Express 路由的基本结构
javascript
app.METHOD(PATH, HANDLER);app:Express 应用实例METHOD:HTTP 请求方法(GET、POST、PUT、DELETE 等)PATH:服务器上的路径HANDLER:当路由匹配时执行的函数
基本路由
GET 请求
javascript
app.get('/', (req, res) => {
res.send('Hello World!');
});POST 请求
javascript
app.post('/', (req, res) => {
res.send('Got a POST request');
});PUT 请求
javascript
app.put('/user', (req, res) => {
res.send('Got a PUT request at /user');
});DELETE 请求
javascript
app.delete('/user', (req, res) => {
res.send('Got a DELETE request at /user');
});路由参数
路由参数是 URL 中的命名段,用于捕获 URL 中指定位置的值。路由参数由冒号 : 前缀标识。
javascript
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(`User ID: ${req.params.userId}, Book ID: ${req.params.bookId}`);
});路由处理函数
路由处理函数可以是单个函数,也可以是多个函数组成的数组。
单个处理函数
javascript
app.get('/example', (req, res) => {
res.send('Example');
});多个处理函数
javascript
app.get('/example', (req, res, next) => {
console.log('First handler');
next();
}, (req, res) => {
res.send('Second handler');
});处理函数数组
javascript
const handler1 = (req, res, next) => {
console.log('Handler 1');
next();
};
const handler2 = (req, res, next) => {
console.log('Handler 2');
next();
};
const handler3 = (req, res) => {
res.send('Handler 3');
};
app.get('/example', [handler1, handler2, handler3]);路由模块化
为了更好地组织代码,Express 允许将路由定义在单独的模块中。
创建路由模块
javascript
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('Users');
});
router.get('/:id', (req, res) => {
res.send(`User ${req.params.id}`);
});
module.exports = router;使用路由模块
javascript
// app.js
const express = require('express');
const app = express();
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);
app.listen(3000, () => {
console.log('Server running');
});路由前缀
可以为路由模块添加前缀,这样所有路由都会自动包含该前缀。
javascript
app.use('/api/v1', usersRouter);
// 路由会变成 /api/v1/users路由嵌套
可以在路由模块中嵌套其他路由模块。
javascript
// routes/users.js
const express = require('express');
const router = express.Router();
const postsRouter = require('./posts');
router.use('/:userId/posts', postsRouter);
module.exports = router;
// routes/posts.js
const express = require('express');
const router = express.Router({ mergeParams: true });
router.get('/', (req, res) => {
res.send(`Posts for user ${req.params.userId}`);
});
module.exports = router;路由中间件
可以为特定的路由应用中间件。
javascript
// 应用于所有路由
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 应用于特定路由
app.use('/users', (req, res, next) => {
console.log('Users route');
next();
});
// 应用于特定路由和方法
app.get('/users', (req, res, next) => {
console.log('GET /users');
next();
}, (req, res) => {
res.send('Users');
});路由参数验证
可以使用中间件验证路由参数。
javascript
app.get('/users/:id', (req, res, next) => {
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).send('Invalid user ID');
}
next();
}, (req, res) => {
res.send(`User ${req.params.id}`);
});404 处理
可以添加一个通配符路由来处理 404 错误。
javascript
app.use((req, res) => {
res.status(404).send('Not Found');
});路由最佳实践
1. 命名约定
- 使用清晰、描述性的路由路径
- 遵循 RESTful 设计原则
- 保持路由路径的一致性
2. 代码组织
- 将路由定义在单独的模块中
- 按功能组织路由
- 使用控制器处理业务逻辑
3. 错误处理
- 为每个路由添加错误处理
- 使用统一的错误处理中间件
- 提供清晰的错误信息
4. 安全性
- 验证用户输入
- 防止 SQL 注入
- 防止 XSS 攻击
- 使用 HTTPS
5. 性能优化
- 避免在路由处理函数中执行 CPU 密集型操作
- 使用缓存
- 合理使用中间件
实践练习
- 创建一个包含多个路由的 Express 应用
- 实现 RESTful API 路由
- 使用路由模块化组织代码
- 添加路由参数验证
- 处理 404 错误