The official example code:
/// 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
}
My question is how to pass multi variables ? which one I got from argument?
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()
}
Which MyData
is this data assign to?
I believe that web::data is distinguished by type. You would need to create a new type for each piece of data you'd like to get access to.
If you want to create multiple instances of the same type, you'll need to use the "New Type" pattern. See here for an example: https://doc.rust-lang.org/rust-by-example/generics/new_types.html
In essence, the "instance" of data, and it's name, are one in the same. In a language like java, you might take an approach where there is a map of names to instances, and you'd need to cast to the type of object you expect as the value. In this case, it's strictly keyed on the type itself.
Here is a working example that demonstrates how to have one definition of a Counter, with multiple instances of it. Note that there is a different set of counters per thread: