您现在的位置是:网站首页 > 路由分层与模块化设计文章详情
路由分层与模块化设计
陈川
【
Node.js
】
64710人已围观
5900字
路由分层与模块化设计是构建可维护、可扩展Express应用的关键。合理的分层能够清晰划分职责,模块化则有助于代码复用和团队协作。下面从路由分层策略、模块化实现方式以及实际应用场景展开讨论。
路由分层基础结构
Express应用通常采用三层路由结构:入口路由→业务路由→控制器。基础实现方式如下:
// 入口文件 app.js
const userRouter = require('./routes/users');
app.use('/users', userRouter);
// routes/users.js
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
router.get('/', userController.listUsers);
router.post('/', userController.createUser);
// controllers/userController.js
exports.listUsers = (req, res) => {
// 业务逻辑处理
res.json([...]);
};
这种分层将URL路径匹配、路由分发和业务处理完全分离。实际项目中可以进一步细化:
- 路由层只做路径映射和参数验证
- 控制器处理核心业务逻辑
- 服务层处理数据操作
- 模型层定义数据结构
模块化路由实现
动态路由加载
大型项目需要自动化加载路由模块,避免手动注册每个路由文件:
// utils/routeLoader.js
const fs = require('fs');
const path = require('path');
module.exports = (app) => {
fs.readdirSync(__dirname)
.filter(file => file !== 'index.js')
.forEach(file => {
const route = require(path.join(__dirname, file));
app.use(route.prefix, route.router);
});
};
// routes/users.js
module.exports = {
prefix: '/api/v1/users',
router: require('express').Router()
.get('/', controller.list)
.post('/', controller.create)
};
版本化路由管理
API版本迭代时可采用路径版本控制:
// app.js
app.use('/api/v1', require('./routes/v1'));
app.use('/api/v2', require('./routes/v2'));
// routes/v1/users.js
router.get('/profile', v1UserController.getProfile);
// routes/v2/users.js
router.get('/profile', v2UserController.getProfile);
中间件分层设计
中间件也应该按照功能进行分层管理:
// middleware/auth.js
module.exports = {
basicAuth: (req, res, next) => {
// 基础认证逻辑
next();
},
adminCheck: (req, res, next) => {
// 管理员权限检查
next();
}
};
// routes/admin.js
const { basicAuth, adminCheck } = require('../middleware/auth');
router.use(basicAuth, adminCheck);
路由参数规范化
统一处理路由参数可以提高代码一致性:
// middleware/params.js
module.exports = {
validateUserId: (req, res, next) => {
if (!isValidId(req.params.id)) {
return res.status(400).json({ error: 'Invalid ID' });
}
next();
}
};
// routes/users.js
router.get('/:id',
params.validateUserId,
controller.getUser
);
微服务架构下的路由设计
在微服务架构中,Express路由可以作为API网关:
// gateway/routes/products.js
const axios = require('axios');
router.get('/products/:id', async (req, res) => {
try {
const response = await axios.get(
`http://product-service/${req.params.id}`
);
res.json(response.data);
} catch (err) {
res.status(502).json({ error: 'Service unavailable' });
}
});
性能优化策略
路由设计直接影响性能,需要注意:
- 避免在路由层进行复杂计算
- 高频路由路径应该尽量短
- 合理使用路由缓存
// 使用route cache
const apicache = require('apicache');
const cache = apicache.middleware;
router.get('/popular-items',
cache('10 minutes'),
controller.getPopularItems
);
测试策略
路由应该单独进行测试,与业务逻辑分离:
// test/routes/users.test.js
const request = require('supertest');
const app = require('../../app');
describe('GET /users', () => {
it('should return 200', async () => {
const res = await request(app)
.get('/api/v1/users')
.expect(200);
expect(Array.isArray(res.body)).toBeTruthy();
});
});
错误处理标准化
统一错误处理中间件应该放在路由最后:
// middleware/errorHandler.js
module.exports = (err, req, res, next) => {
console.error(err.stack);
res.status(500).json({
code: err.code || 'UNKNOWN_ERROR',
message: err.message
});
};
// app.js
app.use('/api', apiRouter);
app.use(errorHandler); // 最后加载
路由元数据管理
为路由添加元数据便于生成文档:
// decorators/routeMeta.js
module.exports = (meta) => {
return (target, key, descriptor) => {
descriptor.value.__routeMeta = meta;
return descriptor;
};
};
// controllers/userController.js
class UserController {
@routeMeta({
description: 'Get user list',
params: ['page', 'limit']
})
static async listUsers(req, res) {
// ...
}
}
前端路由与服务端路由协同
在前后端分离项目中保持路由一致性:
// shared/routes.js
module.exports = {
user: {
profile: (id) => `/users/${id}/profile`,
update: (id) => `/users/${id}`
}
};
// 服务端路由
router.get(sharedRoutes.user.profile(':id'), controller.getProfile);
// 前端请求
axios.get(sharedRoutes.user.profile(123));
路由配置中心化
将路由配置集中管理:
// config/routes.js
module.exports = [
{
path: '/users',
method: 'get',
handler: 'userController.list',
middleware: ['auth']
},
// 其他路由配置...
];
// utils/routeBuilder.js
routesConfig.forEach(config => {
const middlewares = config.middleware
.map(m => require(`../middleware/${m}`));
app[config.method](
config.path,
...middlewares,
require(`../controllers/${config.handler}`)
);
});
动态路由权限控制
基于角色的动态路由权限管理:
// middleware/dynamicAuth.js
module.exports = (requiredRole) => {
return (req, res, next) => {
if (req.user.role !== requiredRole) {
return res.sendStatus(403);
}
next();
};
};
// routes/admin.js
router.get('/dashboard',
dynamicAuth('admin'),
adminController.dashboard
);
路由性能监控
添加路由性能追踪:
// middleware/performance.js
module.exports = (req, res, next) => {
const start = process.hrtime();
res.on('finish', () => {
const diff = process.hrtime(start);
const ms = diff[0] * 1e3 + diff[1] * 1e-6;
console.log(`${req.method} ${req.path} took ${ms.toFixed(2)}ms`);
});
next();
};
// app.js
app.use(performanceMiddleware);
路由版本迁移策略
处理API版本迁移时的路由兼容:
// middleware/versionRedirect.js
module.exports = (options) => {
return (req, res, next) => {
if (req.headers['x-api-version'] === '1.0') {
return res.redirect(301, `/v1${req.path}`);
}
next();
};
};
// app.js
app.use(versionRedirect());
app.use('/v2', v2Router);
上一篇: 环境配置与多环境管理
下一篇: 控制器与服务的分离