You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:15:08