使用axum+deadpool-postgres时,async获取Pool致with_state编译错误求方案
解决方案:Axum + Deadpool-Postgres 状态传递报错问题
你的编译错误核心是主路由与嵌套子路由的状态类型不匹配:主路由通过.with_state()传入Pool,但子路由test_routes()返回的是OpenApiRouter<()>(状态为单元类型),二者类型无法兼容,导致编译失败。除了Extension,还有以下两种可行方案:
方案1:统一路由状态类型
修改子路由的状态类型,使其与主路由保持一致,这样就能正常使用.with_state()传递连接池:
修改子路由定义(test.rs)
use deadpool_postgres::Pool; // 将返回类型从 OpenApiRouter<()> 改为 OpenApiRouter<Pool> pub fn test_routes() -> OpenApiRouter<Pool> { OpenApiRouter::new() .routes(routes!(test_post_1, test_post_2)) }
在处理函数中提取状态
处理请求时,通过State提取器获取连接池:
async fn test_post_1(State(pool): State<Pool>) -> impl IntoResponse { // 从连接池获取连接并执行数据库操作 let client = pool.get().await.unwrap(); // ... 业务逻辑 "Success".into_response() }
主路由保持原有写法
此时主路由的.with_state(database_pool().await)就能正常编译,因为主路由与子路由的状态类型统一为Pool。
方案2:使用全局初始化的连接池(不推荐,但可行)
通过异步全局初始化工具(如once_cell)将连接池设为全局变量,避免通过路由状态传递:
初始化全局连接池
use once_cell::sync::Lazy; use deadpool_postgres::Pool; static POOL: Lazy<Pool> = Lazy::new(|| { tokio::runtime::Runtime::new().unwrap().block_on(async { // 此处复用你的 database_pool() 逻辑 database_pool().await }) });
在处理函数中直接使用
async fn test_post_1() -> impl IntoResponse { let client = POOL.get().await.unwrap(); // ... 业务逻辑 "Success".into_response() }
注意:全局状态会降低代码的可测试性和扩展性,仅在小型项目或快速原型中考虑使用。
补充:Extension方案的正确写法(你已找到的方案)
如果选择保留子路由的()状态类型,可通过Extension传递连接池:
主路由添加扩展层
use axum::Extension; use axum::middleware::AddExtensionLayer; let pool = database_pool().await; let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi()) .nest("/test", test_routes()) .layer(AddExtensionLayer::new(pool)) // 替换 with_state 为扩展层 .split_for_parts();
处理函数提取扩展
async fn test_post_1(Extension(pool): Extension<Pool>) -> impl IntoResponse { let client = pool.get().await.unwrap(); // ... 业务逻辑 "Success".into_response() }
内容的提问来源于stack exchange,提问作者Grimlock
相关产品推荐
相关产品推荐

