2. 基于 Express 实现路由分发与参数解析
Express 路由分发与参数解析
Express 的核心能力之一是把不同 URL 映射到不同处理函数。路径中的动态段用 :name 声明,通过 req.params 读取;查询字符串通过 req.query 读取。路由按注册顺序依次匹配,先命中的处理函数先执行,因此顺序会直接影响结果。
关键对象:
app.get(path, handler)、req.params、req.query、req.path、req.method。
路由匹配顺序与参数来源
完整可运行示例
下面代码定义四个路由,覆盖动态参数、固定路径、查询字符串和 404 兜底。启动后可用浏览器或 curl 依次访问验证。
// app.js
const express = require('express');
const app = express();
const PORT = 3000;
// ① 动态参数路由:/users/42 → req.params.id = "42"
app.get('/users/:id', (req, res) => {
res.json({
route: '/users/:id',
params: req.params, // { id: "42" }
query: req.query, // { role: "admin" }
path: req.path // "/users/42"
});
});
// ② 固定路径路由:/users/admin
// 注意:必须注册在 /users/:id 之前,否则会被 :id 捕获
app.get('/users/admin', (req, res) => {
res.json({ route: '/users/admin', message: '管理员页面' });
});
// ③ 查询字符串路由:/search?q=node&limit=5
app.get('/search', (req, res) => {
const { q = '', limit = '10' } = req.query;
res.json({
route: '/search',
keyword: q,
limit: Number(limit),
hasKeyword: q.length > 0
});
});
// ④ 404 兜底:所有未匹配的请求
app.use((req, res) => {
res.status(404).json({
error: 'Not Found',
method: req.method,
path: req.path
});
});
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
验证与观察
| 请求 | 命中路由 | 关键输出 |
|---|---|---|
GET /users/42?role=admin |
① /users/:id | params.id="42",query.role="admin" |
GET /users/admin |
② /users/admin(若顺序正确) | message="管理员页面" |
GET /search?q=node&limit=5 |
③ /search | keyword="node",limit=5 |
GET /unknown |
④ 404 兜底 | status=404,error="Not Found" |
把
/users/admin 移到 /users/:id 之前再请求 /users/admin,观察响应从“管理员页面”变为 params.id="admin",即可直观看到注册顺序对匹配结果的影响。
req.params 的值始终是字符串;req.query 的值也是字符串或字符串数组。需要数字时应显式转换,例如 Number(req.query.limit),否则后续计算可能得到意外结果。