Rust actix-web使用自定义trait作为app_data报Sized未实现错误如何解决
错误根因
两个报错都是围绕dyn AsyncKeyProvider是动态大小类型(DST)、不满足Sized约束导致的:
Arc::new要求传入的参数是编译期大小确定的Sized类型,你不能直接用它构造trait对象,需要先构造具体类型的Arc再通过unsized coercion转换为trait对象的Arcactix_web::web::Data的into_inner()方法要求内层的T满足Sized约束,因为它要转移内部Arc<T>的所有权,动态大小的trait对象不满足这个约束,所以无法调用该方法。
可行解决方案
方案1:保留多态特性,直接调用trait方法(最常用)
如果你不需要拿到GoogleKeyProvider的具体实例,只是要调用AsyncKeyProvider trait定义的方法,完全不需要调用into_inner,web::Data本身实现了Deref trait,可以直接调用trait的方法。
首先修正初始化代码的类型转换写法:
// 先初始化具体的GoogleKeyProvider实例 let google_provider = GoogleKeyProvider { cached: None, expiration_time: Instant::now(), }; // 先构造具体类型的Arc,再显式转换为trait对象的Arc,最后包成web::Data let key_provider: web::Data<dyn AsyncKeyProvider> = web::Data::from( Arc::new(google_provider) as Arc<dyn AsyncKeyProvider> );
然后在validate函数中直接调用方法即可,不需要into_inner:
pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<dyn AsyncKeyProvider>) -> impl Responder { // 直接通过provider调用trait方法即可,不需要取内层实例 let key = provider.get_key_async(&jwt_body.key_id).await; // 后续业务逻辑 }
方案2:直接存储具体类型(适合无需多态的场景)
如果你只有GoogleKeyProvider这一种密钥提供器实现,不需要多态切换不同的实现,可以直接存储具体类型的实例,就可以正常调用into_inner了:
初始化代码修改为:
let google_provider = GoogleKeyProvider { cached: None, expiration_time: Instant::now(), }; let key_provider = web::Data::new(google_provider);
对应的validate函数参数修改为具体类型:
pub async fn validate(jwt_body: web::Json<JwtBody>, provider: web::Data<GoogleKeyProvider>) -> impl Responder { // 此时可以正常调用into_inner,因为GoogleKeyProvider是Sized类型 let provider_object = provider.into_inner(); // 后续业务逻辑 }
内容的提问来源于stack exchange,提问作者dantdj
相关产品推荐
相关产品推荐

