Express 路由基础
🎯 引言
学完这篇文章,你能为服务器定义 GET、POST、PUT、DELETE 各种请求方法的路由,会读取路径参数和查询参数,还能用 express.Router 把路由拆分到独立文件,让项目结构更清晰。
🧱 什么是路由
路由就是“地址 + 请求方法”到“处理函数”的映射规则。 客户端请求 /users,服务器该执行哪段代码,就是路由说了算。
就像快递分拣中心:包裹(请求)到了,根据地址标签(URL)和类型(请求方法),分到不同的货架(处理函数)去。
🛠 四种常用请求方法
REST 风格的接口里,不同的请求方法对应不同的操作语义,Express 为每种方法提供了对应的注册函数:
import express from 'express';
const app = express();
app.get('/users', (req, res) => {
res.send('获取用户列表');
});
app.post('/users', (req, res) => {
res.send('新增一个用户');
});
app.put('/users', (req, res) => {
res.send('更新用户信息');
});
app.delete('/users', (req, res) => {
res.send('删除一个用户');
});
app.listen(3000);
地址相同、方法不同,会被路由到不同的处理函数,它们各司其职:
GET:查询数据,浏览器地址栏直接访问就是 GET 请求。POST:新增数据,通常携带请求体。PUT:更新数据。DELETE:删除数据。
🛠 路径参数 req.params
接口经常需要根据 ID 操作某条数据,比如 /users/1 表示 1 号用户。ID 是变化的,不能为每个用户写一条路由,这时用路径参数:
app.get('/users/:id', (req, res) => {
res.send(`用户详情:${req.params.id}`);
});
路径里的 :id 是占位符,访问 /users/1、/users/99 都能匹配这条路由,实际的值通过 req.params.id 拿到。
req.params 拿到的值永远是字符串。访问 /users/1 时 req.params.id 是 '1' 而不是数字 1,需要数字计算时记得用 Number() 转换。🛠 查询参数 req.query
URL 问号后面的键值对叫查询参数,常用于分页、筛选,比如 /users?page=2&size=10。Express 自动解析好放在 req.query 里:
app.get('/users', (req, res) => {
const { page, size } = req.query;
res.send(`第 ${page} 页,每页 ${size} 条`);
});
访问 http://localhost:3000/users?page=2&size=10,就会返回“第 2 页,每页 10 条”。
req.query 是一个只读的 getter 属性,读取没问题,但不要尝试给它重新赋值。⚡ 路径参数与查询参数怎么选
两者都能从 URL 里带数据,使用场景不同:
- 路径参数:定位某一条具体资源,是 URL 结构的一部分,如
/users/1。 - 查询参数:附加的筛选条件,可有可无,如
?page=2&keyword=张。
记住一个判断标准:少了它接口就不知道操作谁,用路径参数;少了它接口依然能用默认值工作,用查询参数。
🛠 用 express.Router 拆分路由
所有路由都堆在 app.js 里,接口一多就没法维护。Router 是一个迷你版的路由对象,可以把同一类路由拆到独立文件:
import { Router } from 'express';
const router = Router();
// 这里的 / 实际对应挂载路径 /users
router.get('/', (req, res) => {
res.send('用户列表');
});
router.get('/:id', (req, res) => {
res.send(`用户详情:${req.params.id}`);
});
export default router;
然后在入口文件里挂载:
import express from 'express';
import userRouter from './routes/user.js';
const app = express();
// 以 /users 开头请求交给 userRouter 处理
app.use('/users', userRouter);
app.listen(3000);
这样访问 /users 和 /users/1 都会进入 routes/user.js。以后再加文章路由,就新建 routes/article.js 挂载到 /articles,每个文件只管自己的事。
.js,写 import userRouter from './routes/user' 会报找不到模块,这一点上一个 Node.js 课程强调过。💡 all 与 use 的区别
除了按方法注册,还有两个不太常用的写法,了解即可:
app.all('/users', handler):不管 GET、POST 还是其他方法,统统走这个处理函数。app.use('/users', handler):匹配以/users开头的所有路径、所有方法,常用于挂载 Router 和中间件。
all 要求路径精确匹配,use 是前缀匹配,这是两者关键的区别。日常开发里按具体方法写 app.get、app.post 才是主流。
🧾 小节总结
- 路由是“地址 + 请求方法”到处理函数的映射,Express 用
app.get、app.post、app.put、app.delete注册。 - 路径参数用
:id占位,通过req.params读取,拿到的值是字符串。 - 查询参数是问号后的键值对,通过
req.query读取,Express 5 中它是只读的。 express.Router可以把一类路由拆到独立文件,再用app.use('/users', router)挂载。app.all匹配所有方法且路径精确,app.use匹配所有方法且按前缀匹配。
❓ 知识问答
Q1:路径参数和查询参数能同时用吗?
可以。比如 /users/1/comments?page=2,req.params.id 拿到用户 ID,req.query.page 拿到页码,互不干扰。
Q2:/users/:id 和 /users/new 两条路由都写了,访问 /users/new 走哪条?
Express 按注册顺序匹配,先注册的先命中。想让 /users/new 生效,要把它写在 /users/:id 前面,否则 new 会被当成 id。
Q3:Router 拆出去后,路径要怎么写?
Router 文件里写相对路径。挂载时指定了 /users,Router 里的 / 就是 /users,/:id 就是 /users/:id,不要在 Router 里再写一遍完整路径。
Q4:GET 请求能带请求体吗?
规范上 GET 没有请求体,要传数据就用路径参数或查询参数。需要提交数据时,请使用 POST、PUT 等方法。
🧪 小练习
为图书模块写路由并拆分到独立文件:
- 新建
routes/book.js,定义两条路由:GET /books返回“图书列表”,GET /books/:id返回“图书详情:id 值”。 - 在
app.js中把它挂载到/books路径下。
// 请在这里编写代码
import express from 'express';
const app = express();
// 请在这里编写代码
app.listen(3000);
🎉 恭喜你已经掌握 Express 路由的常用写法!下一篇我们学习 Express 的灵魂:中间件机制。
