真实系统里,路由不会全写在一个文件。
Axum 的组合方式主要有三种:
nestmergefallback
#1. nest:把一片分关挂到某个前缀下面
let api = Router::new()
.route("/permits", get(list_permits))
.route("/permits/{id}", get(get_permit));
let app = Router::new().nest("/api", api);得到的是:
总关
└── /api
├── GET /permits
└── GET /permits/{id}#2. merge:把两张并列关口图拼起来
let permits = Router::new().route("/permits", get(list_permits));
let users = Router::new().route("/users", get(list_users));
let app = Router::new().merge(permits).merge(users);得到的是:
总关
├── GET /permits
└── GET /users#3. fallback:所有没命中的车,统一去兜底窗口
async fn not_found() -> impl IntoResponse {
(StatusCode::NOT_FOUND, "这条通关线路不存在")
}
let app = Router::new()
.route("/health", get(health))
.fallback(not_found);#4. 一个很关键的工程点
官方文档对 nest 和 merge 都反复强调:
组合 Router 时,状态类型必须一致。
所以你如果模块化分关,脑子里要有这张图:
模块化 Axum
├── permits_routes() -> Router<AppState>
├── users_routes() -> Router<AppState>
└── main 里 merge / nest 再统一 with_state(...)还有一点经常被忽略:
merge时只能有一个 fallbacknest的内层 Router 仍会继承外层 fallback