如何通过 actix-web App::data() 传递多变量

How can I pass multi variable by actix-web App::data()

官方示例代码: 官方示例代码:

    /// use std::cell::Cell;
    /// use actix_web::{web, App, HttpResponse, Responder};
    ///
    /// struct MyData {
    ///     counter: Cell<usize>,
    /// }
    ///
    /// async fn index(data: web::Data<MyData>) -> impl Responder {
    ///     data.counter.set(data.counter.get() + 1);
    ///     HttpResponse::Ok()
    /// }
    ///
    /// let app = App::new()
    ///     .data(MyData{ counter: Cell::new(0) })
    ///     .service(
    ///         web::resource("/index.html").route(
    ///             web::get().to(index)));
    /// 
    pub fn data<U: 'static>(mut self, data: U) -> Self {
        self.data.push(Box::new(Data::new(data)));
        self
    }

我的问题是如何传递多变量?我从争论中得到了哪一个?

let app = App::new()
         .data(MyData{ counter: Cell::new(0) })       // <-- multi 
         .data(MyData{ counter: Cell::new(100) })     // <-- multi 
         .data(MyData{ counter: Cell::new(200) })     // <-- multi 
         .service(
             web::resource("/index.html").route(
                 web::get().to(index)));

// which MyData is this data assign to?
async fn index(data: web::Data<MyData>) -> impl Responder {
    data.counter.set(data.counter.get() + 1);
    HttpResponse::Ok()
}

这个数据分配给了哪个MyData? 此数据分配给哪个 MyData?

我相信web::data是按类型区分的。您需要为要访问的每条数据创建一个新类型。

如果您想创建同一类型的多个实例,则需要使用“新类型”模式。示例见此处:https://doc.rust-lang.org/rust-by-example/generics/new_types.html

从本质上讲,数据的“实例”和它的名字是同一个东西。在像 java 这样的语言中,您可能会采用一种方法,其中存在名称到实例的映射,并且您需要转换为您期望的对象类型作为值。在这种情况下,它严格以类型本身为键。

这是一个工作示例,它演示了如何使用一个计数器定义及其多个实例。请注意,每个线程有一组不同的计数器 :

use std::cell::Cell;
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};

struct Counter {
    counter: Cell<usize>,
}

impl Counter {
    pub fn new(value: usize) -> Counter {
        Counter { counter: Cell::new(value) }
    }

    pub fn increment(&self) -> usize {
        self.counter.set(self.counter.get() + 1);
        self.counter.get()
    }
}

struct SuccessCounter(Counter);

struct FailureCounter(Counter);

#[get("/")]
async fn index(success_counter: web::Data<SuccessCounter>,
               failure_counter: web::Data<FailureCounter>) -> impl Responder {
    println!("Successes: {}", success_counter.0.increment());
    println!("Failures: {}", failure_counter.0.increment());
    HttpResponse::Ok()
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .data(SuccessCounter(Counter::new(0)))
            .data(FailureCounter(Counter::new(100)))
            .service(index)
    })
        .bind("127.0.0.1:8080")?
        .run()
        .await
}