Skip to content
On this page

Express路由系统

路由定义了应用如何响应客户端对特定端点的请求,包括请求的URL路径和HTTP方法。每个路由可以有一个或多个处理函数,当路由匹配时执行。

路由定义

路由在Express中定义为:

javascript
app.METHOD(PATH, HANDLER)
  • app - Express应用实例
  • METHOD - HTTP请求方法 (get, post, put, delete等)
  • PATH - 路由路径(端点)
  • HANDLER - 路由匹配时执行的处理函数

基本路由

简单路由

javascript
const express = require('express');
const app = express();

// GET请求
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// POST请求
app.post('/users', (req, res) => {
  res.send('Creating a user');
});

// PUT请求
app.put('/users/:id', (req, res) => {
  res.send(`Updating user ${req.params.id}`);
});

// DELETE请求
app.delete('/users/:id', (req, res) => {
  res.send(`Deleting user ${req.params.id}`);
});

路由路径

静态路径

javascript
app.get('/users', (req, res) => {
  res.send('Users list');
});

app.get('/users/profile', (req, res) => {
  res.send('User profile');
});

路由参数

使用冒号(:)定义路由参数:

javascript
// 单个参数
app.get('/users/:userId', (req, res) => {
  res.send(`User ID: ${req.params.userId}`);
});

// 多个参数
app.get('/users/:userId/books/:bookId', (req, res) => {
  res.send(`User: ${req.params.userId}, Book: ${req.params.bookId}`);
});

// 可选参数
app.get('/users/:userId?', (req, res) => {
  if (req.params.userId) {
    res.send(`User ID: ${req.params.userId}`);
  } else {
    res.send('No user ID provided');
  }
});

路径模式

javascript
// 模式匹配 - ? 表示可选字符
app.get('/ab?cd', (req, res) => {
  res.send('ab?cd - matches /acd or /abcd');
});

// 模式匹配 - + 表示一个或多个
app.get('/ab+cd', (req, res) => {
  res.send('ab+cd - matches /abcd, /abbcd, /abbbcd, etc');
});

// 模式匹配 - * 表示零个或多个
app.get('/ab*cd', (req, res) => {
  res.send('ab*cd - matches /abcd, /abxcd, /abRANDOMcd, etc');
});

// 模式匹配 - () 表示组
app.get('/ab(cd)?e', (req, res) => {
  res.send('/ab(cd)?e - matches /abe or /abcde');
});

正则表达式路径

javascript
// 匹配以a开头的路径
app.get(/a/, (req, res) => {
  res.send('Path contains "a"');
});

// 匹配以fly结尾的路径
app.get(/.*fly$/, (req, res) => {
  res.send('Path ends with "fly"');
});

// 匹配数字ID
app.get(/\/users\/(\d+)/, (req, res) => {
  res.send('User with numeric ID');
});

路由处理函数

单个处理函数

javascript
app.get('/example', (req, res) => {
  res.send('Hello from a single handler');
});

多个处理函数

javascript
// 多个中间件函数
const handler1 = (req, res, next) => {
  console.log('Handler 1');
  next();
};

const handler2 = (req, res) => {
  res.send('Hello from multiple handlers');
};

app.get('/example', handler1, handler2);

数组处理函数

javascript
const middleware1 = (req, res, next) => {
  console.log('Middleware 1');
  next();
};

const middleware2 = (req, res, next) => {
  console.log('Middleware 2');
  next();
};

app.get('/example', [middleware1, middleware2], (req, res) => {
  res.send('Hello from array handlers');
});

路由方法

Express支持所有HTTP方法:

javascript
app.get('/', (req, res) => { /* GET */ });
app.post('/users', (req, res) => { /* POST */ });
app.put('/users/:id', (req, res) => { /* PUT */ });
app.delete('/users/:id', (req, res) => { /* DELETE */ });
app.patch('/users/:id', (req, res) => { /* PATCH */ });
app.options('/users', (req, res) => { /* OPTIONS */ });
app.head('/users', (req, res) => { /* HEAD */ });

响应方法

路由处理函数中可以使用多种响应方法:

javascript
app.get('/responses', (req, res) => {
  // res.send() - 发送响应
  // res.json() - 发送JSON响应
  // res.jsonp() - 发送JSONP响应
  // res.redirect() - 重定向响应
  // res.render() - 渲染视图模板
  // res.end() - 结束响应
  // res.download() - 提示下载文件
  // res.sendFile() - 发送文件
  // res.sendStatus() - 设置状态码并发送响应

  res.json({
    message: 'Hello World',
    timestamp: new Date()
  });
});

路由参数详解

req.params

包含路由路径中指定的键值对:

javascript
// GET /users/123/books/456
app.get('/users/:userId/books/:bookId', (req, res) => {
  console.log(req.params.userId); // 123
  console.log(req.params.bookId); // 456
  res.send(req.params);
});

req.query

包含URL查询字符串中的键值对:

javascript
// GET /search?q=express&sort=asc
app.get('/search', (req, res) => {
  console.log(req.query.q); // express
  console.log(req.query.sort); // asc
  res.send(req.query);
});

req.body

包含请求体中的数据(需要中间件):

javascript
app.use(express.json()); // 解析JSON请求体

app.post('/users', (req, res) => {
  console.log(req.body.name); // 从请求体获取数据
  res.json({ message: 'User created', user: req.body });
});

Router对象

使用express.Router()创建模块化路由:

javascript
const express = require('express');
const router = express.Router();

// 路由中间件
router.use((req, res, next) => {
  console.log(`Time: ${Date.now()}`);
  next();
});

// 定义路由
router.get('/', (req, res) => {
  res.send('Router homepage');
});

router.get('/about', (req, res) => {
  res.send('Router about page');
});

// 将路由器挂载到应用
app.use('/api', router);

路由模块化

创建路由模块

javascript
// routes/users.js
const express = require('express');
const router = express.Router();

// GET /users
router.get('/', (req, res) => {
  res.json({ message: 'Users list' });
});

// GET /users/:id
router.get('/:id', (req, res) => {
  res.json({ id: req.params.id, name: 'User name' });
});

// POST /users
router.post('/', (req, res) => {
  res.json({ message: 'User created', user: req.body });
});

module.exports = router;

在主应用中使用路由模块

javascript
// app.js
const express = require('express');
const userRoutes = require('./routes/users');

const app = express();

app.use('/users', userRoutes);

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

路由前缀和嵌套

javascript
const express = require('express');
const app = express();

// 带前缀的路由
app.use('/api/v1', (req, res, next) => {
  console.log('API version 1 middleware');
  next();
});

// 嵌套路由
const apiRouter = express.Router();
const userRouter = express.Router();

userRouter.get('/', (req, res) => res.send('Users'));
userRouter.get('/:id', (req, res) => res.send(`User ${req.params.id}`));

apiRouter.use('/users', userRouter);
app.use('/api', apiRouter);

路由重定向

javascript
// 临时重定向 (302)
app.get('/old-path', (req, res) => {
  res.redirect('/new-path');
});

// 永久重定向 (301)
app.get('/old-page', (req, res) => {
  res.redirect(301, '/new-page');
});

// 重定向到外部URL
app.get('/external', (req, res) => {
  res.redirect('https://example.com');
});

错误路由处理

javascript
// 404处理
app.use((req, res, next) => {
  res.status(404).send('Route not found');
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

高级路由模式

路由参数验证

javascript
// 使用正则表达式验证参数
app.get('/users/:userId(\\d+)', (req, res) => {
  // 只匹配数字类型的userId
  res.send(`User ID: ${req.params.userId}`);
});

// 自定义参数验证中间件
app.param('userId', (req, res, next, id) => {
  if (id.length !== 24) {
    next(new Error('Invalid user ID'));
  } else {
    next();
  }
});

Express的路由系统非常灵活和强大,通过合理使用路由参数、模式匹配和中间件,可以构建复杂而高效的Web应用路由结构。