后端只有一条路由:聊聊我的自定义 Dispatcher 设计

📅 发布时间:2026/7/31 2:09:52
后端只有一条路由:聊聊我的自定义 Dispatcher 设计 前两篇聊了背单词小程序「优词记 Pro」的整体架构和请求层封装今天说说后端一个比较激进的设计整个项目的路由文件只有一行。路由文件的痛常规做法是每个接口注册一条路由。项目小的时候没问题接口一多路由文件就变成几百行的流水账改个接口要同时动路由和控制器命名风格慢慢漂移review 时还得对着路由表找实现。既然我的接口 URL 本来就有强规律为什么不让规律本身当路由于是全站只留一条通配路由所有请求交给一个 Dispatcher 统一调度Router::addRoute([GET,POST,PUT,DELETE], /{name:.}, Dispatcher::class . handle);三条约定替代整张路由表约定一URL 前缀分端。/admin/*走管理端控制器目录/user/*走小程序端/common/*两端通用。不同端的认证策略也随前缀确定——管理端 JWT 有效期 7 天小程序端 365 天通用接口两种身份都放行。约定二HTTP 方法映射方法前缀。GET →get*POST →create*PUT →update*DELETE →delete*。语义直接编码在方法名里看到createOrder就知道它只接受 POST。约定三URL 段转驼峰拼方法名。kebab-case 的 URL 段转成 camelCase 后匹配控制器和方法比如GET /admin/user/list-page会命中User::getListPage()。找不到控制器时还有一次目录归约兜底Foo\Bar未命中就回退找Foo\Bar\Index。请求命中GET /admin/user/list-pageAdminPort\User::getListPage()POST /user/collectionUserPort\Collection::create()DELETE /admin/advertAdminPort\Advert::delete()新增一个接口只需要在对应目录放好控制器、按前缀命名方法路由自动就通了git diff 里只有一个文件。认证和权限也挂在约定上Dispatcher 找到目标方法后先过认证再执行。默认全部接口要求登录例外用#[NoNeedLogin]注解显式声明需要细粒度权限的方法加#[Permission([manage-advert-add])]由注解在调度时统一校验。权限、日志这些横切逻辑都收敛在调度层业务控制器保持干净。代价与取舍约定路由不是免费的。两点代价说在前面一是新人要先学约定不看文档很难从 URL 直接反查代码位置所以约定必须写进 README 并且从不破例二是灵活性受限比如当前实现不允许向方法传位置参数多余的 URL 段直接 404——这是有意为之宁可严格也不要歧义。对单人或小团队项目用这点学习成本换掉整张路由表的维护成本我认为很值。明天写写这套后端更「离经叛道」的部分不写 migration直接从数据库 schema 反向生成 Entity 和 Model 代码感兴趣的可以关注。