Skip to content

路由管理

什么是路由

路由是指确定应用如何响应客户端对特定端点的请求,这些端点由 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 密集型操作
  • 使用缓存
  • 合理使用中间件

实践练习

  1. 创建一个包含多个路由的 Express 应用
  2. 实现 RESTful API 路由
  3. 使用路由模块化组织代码
  4. 添加路由参数验证
  5. 处理 404 错误

基于 VitePress 的本地知识库