在Web开发中,路由是连接用户请求与业务逻辑的核心桥梁,它负责将不同URL路径和HTTP方法映射到对应的处理函数,Egg.js作为阿里巴巴开源的企业级Node.js框架,其路由系统继承了Koa的简洁性,同时通过约定优于配置的理念,提供了高度可维护、可扩展的路由管理能力,本文将围绕Egg.js的路由机制展开,从基础定义到高级特性,详细解析其设计思路与使用方法。

路由基础:定义与映射
Egg.js中的路由通过app/router.js文件进行集中管理,开发者可以通过app.router或直接在文件中使用app.method()(如app.get、app.post)来定义路由规则,其核心是将HTTP请求的路径(path)和方法(method)与控制器(Controller)中的方法绑定,实现请求的精准分发。
定义一个GET请求的路由,用于获取用户信息:
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/users/:id', controller.user.getUser); // 路径参数:id
};
这里,/users/:id是一个带路径参数的路由,id表示动态参数,当请求/users/123时,参数id的值为"123",最终请求会交由controller.user.getUser方法处理,Egg.js支持所有标准HTTP方法,包括get、post、put、delete、patch等,方法名与HTTP方法一一对应,语义清晰。
路由参数:灵活获取请求数据
Egg.js路由支持多种参数类型,包括路径参数、查询参数和请求体参数,满足不同场景下的数据获取需求。
路径参数
路径参数通过在路由路径中定义,如/users/:id中的id,在控制器中,可通过ctx.params获取所有路径参数组成的对象,
// app/controller/user.js
exports.getUser = async ctx => {
const { id } = ctx.params; // 获取路径参数id
ctx.body = { userId: id };
};
查询参数
查询参数是URL中后的键值对,如/users?page=1&size=10,通过ctx.query可获取解析后的查询参数对象:
exports.listUser = async ctx => {
const { page = 1, size = 10 } = ctx.query; // 默认值处理
ctx.body = { page, size };
};
请求体参数
对于POST、PUT等携带请求体的方法,Egg.js通过中间件bodyParser自动解析请求体(支持JSON、form-data、x-www-form-urlencoded等格式),开发者可通过ctx.request.body获取数据:
exports.createUser = async ctx => {
const { name, age } = ctx.request.body;
ctx.body = { name, age };
};
为更直观地对比参数类型,以下表格总结了不同参数的获取方式:
| 参数类型 | 获取方式 | 示例URL | 控制器中获取方式 |
|---|---|---|---|
| 路径参数 | ctx.params |
/users/123 |
ctx.params.id |
| 查询参数 | ctx.query |
/users?page=1 |
ctx.query.page |
| 请求体参数 | ctx.request.body |
POST { "name": "Tom" } |
ctx.request.body.name |
路由分组:模块化管理
当项目规模扩大时,路由数量会急剧增加,Egg.js通过路由分组(app.group)实现模块化管理,避免重复前缀和中间件逻辑,将所有用户相关的路由统一管理:

// app/router.js
module.exports = app => {
const { router, controller } = app;
const userRouter = router.group('/api/v1/user'); // 定义分组前缀
userRouter.get('/:id', controller.user.getUser); // 实际路径:/api/v1/user/:id
userRouter.post('/', controller.user.createUser);
};
分组不仅支持统一前缀,还能批量绑定中间件,为用户分组添加权限校验中间件:
const authMiddleware = app.middleware.auth(); // 自定义权限中间件 userRouter.use(authMiddleware); // 分组内所有路由生效
中间件:增强路由能力
中间件是Egg.js路由的核心扩展机制,它可以在请求到达控制器前或响应返回后执行预处理逻辑,如日志记录、权限校验、数据校验等,Egg.js支持路由级中间件,即中间件仅对当前路由或分组路由生效。
路由级中间件
在定义路由时,通过middleware选项指定中间件:
router.get('/admin', app.middleware.auth(), controller.admin.index);
这里,app.middleware.auth()是一个自定义的权限校验中间件,只有通过校验的请求才能访问/admin路由。
中间件执行顺序
中间件的执行遵循“洋葱模型”,即请求进入时按定义顺序执行,离开时按逆序执行。
router.get('/test', middlewareA, middlewareB, controller.test);
执行流程为:请求进入 → middlewareA预处理 → middlewareB预处理 → controller.test处理 → middlewareB后处理 → middlewareA后处理 → 返回响应。
动态路由与通配符
Egg.js支持动态路由和通配符,满足复杂路径匹配需求。
正则表达式参数
通过在路径参数中定义正则表达式,限制参数格式,限制id必须为数字:
router.get('/users/:id(\d+)', controller.user.getUser); // 仅匹配数字id
请求/users/abc将返回404,而/users/123正常匹配。

通配符路由
使用匹配任意路径,常用于404处理或动态代理:
router.all('*', controller.notFound); // 匹配所有未定义的路由
错误处理:健壮的路由异常捕获
路由处理过程中可能抛出异常(如参数错误、数据库错误),Egg.js通过全局异常中间件统一捕获,同时支持路由级错误处理,在控制器中手动抛出错误:
exports.getUser = async ctx => {
const { id } = ctx.params;
if (!id) {
throw new Error('userId is required'); // 抛出异常
}
ctx.body = { userId: id };
};
全局异常中间件(如app/middleware/error.js)会捕获此类异常并返回统一格式的错误响应,避免直接暴露错误信息给用户。
高级特性:多应用与控制器关联
多应用路由
在多应用架构(如通过egg-plugin-multiapp插件)中,每个子应用可独立管理路由,通过app.subapp访问子应用路由,实现模块解耦。
控制器关联
Egg.js支持将路由与控制器类直接关联,减少手动绑定的代码量,通过app/controller目录下的文件结构,框架会自动将路由映射到对应控制器方法。app/controller/user.js中的getUser方法,可通过router.get('/user', 'user.getUser')绑定,无需引入controller对象。
Egg.js的路由系统通过简洁的API设计、灵活的参数处理、强大的分组与中间件机制,为开发者提供了高效、可维护的路由管理方案,无论是小型项目还是大型企业级应用,其“约定优于配置”的理念都能帮助开发者快速构建结构清晰、扩展性强的Web服务,掌握Egg.js路由的核心特性,不仅能提升开发效率,更能为后续的代码维护和迭代奠定坚实基础。
相关问答FAQs
Q1:Egg.js中如何实现路由级别的权限控制?
A:可通过路由中间件实现权限控制,首先自定义一个权限校验中间件(如app/middleware/auth.js),在中间件中根据用户角色或权限判断是否放行,然后在路由或路由分组中绑定该中间件。
// app/middleware/auth.js
module.exports = () => {
return async (ctx, next) => {
const token = ctx.header.authorization;
if (!token) {
ctx.throw(401, 'Unauthorized');
}
// 校验token逻辑...
await next();
};
};
// app/router.js
router.get('/admin', app.middleware.auth(), controller.admin.index);
Q2:Egg.js路由分组时如何统一处理跨域问题?
A:可自定义跨域中间件,并在路由分组中批量绑定,定义app/middleware/cors.js中间件:
module.exports = () => {
return async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (ctx.method === 'OPTIONS') {
ctx.status = 204;
} else {
await next();
}
};
};
// 在分组中绑定
router.group('/api', app.middleware.cors(), controller.api);
来源互联网整合,作者:小编,如若转载,请注明出处:https://www.aiboce.com/ask/264681.html