如何在Rust Axum中将PgPool状态传递给嵌套路由?
解决Axum中路由嵌套时数据库连接池的状态传递问题
核心问题分析
你遇到的两个类型不匹配错误,本质是主路由、嵌套路由、处理函数三者的状态类型不一致:
- 主路由默认状态类型为
(),但你传递了&PgPool,导致类型不匹配; - 嵌套路由未声明状态类型(默认
()),但处理函数需要PgPool类型的状态,导致MethodRouter类型冲突。
方案一:直接利用PgPool的可克隆特性(推荐,PgPool内部已用Arc实现共享)
1. 修改嵌套路由的返回类型
明确嵌套路由的状态类型为PgPool:
use axum::Router; use sqlx::postgres::PgPool; pub fn create_products_router() -> Router<PgPool> { Router::new() .route("/products", get(get_products_list::get_products_list)) }
2. 调整主路由的状态传递
直接传递PgPool的所有权(PgPool的Clone是轻量级的,内部共享连接池实例):
// main函数中 let pool = PgPoolOptions::new() .max_connections(5) .acquire_timeout(Duration::from_secs(3)) .connect(&db_connection_str) .await .expect("can't connect to database"); let app = Router::new() .nest("/products", create_products_router()) .with_state(pool); // 直接传递PgPool,无需引用
3. 处理函数保持原样
处理函数中的State<PgPool>可以直接提取状态:
use axum::extract::State; use sqlx::postgres::PgPool; use axum::http::StatusCode; pub async fn get_products_list(State(pool): State<PgPool>) -> Result<String, (StatusCode, String)> { sqlx::query_scalar("select * from product") .fetch(&pool) .await .map_err(internal_error) }
方案二:手动用Arc包裹连接池(适用于需要显式共享的场景)
如果需要更明确的共享语义,可以用Arc包裹PgPool:
1. 包裹连接池
use std::sync::Arc; // main函数中 let pool = Arc::new(PgPoolOptions::new() .max_connections(5) .acquire_timeout(Duration::from_secs(3)) .connect(&db_connection_str) .await .expect("can't connect to database"));
2. 修改嵌套路由的状态类型
pub fn create_products_router() -> Router<Arc<PgPool>> { Router::new() .route("/products", get(get_products_list::get_products_list)) }
3. 调整处理函数的状态提取
pub async fn get_products_list(State(pool): State<Arc<PgPool>>) -> Result<String, (StatusCode, String)> { sqlx::query_scalar("select * from product") .fetch(&*pool) // 解引用Arc获取PgPool引用 .await .map_err(internal_error) }
4. 主路由传递状态
let app = Router::new() .nest("/products", create_products_router()) .with_state(pool);
关键说明
- Axum的路由状态是层级继承的:如果父路由设置了状态,子路由若未单独设置状态,会自动继承父路由的状态类型;
sqlx的PgPool本身已经通过内部Arc实现了线程安全的共享,因此直接克隆PgPool是高效且安全的,无需手动包裹Arc(方案一足够)。
内容的提问来源于stack exchange,提问作者Kadiem Alqazzaz
相关产品推荐
相关产品推荐

