2

有没有办法让actix-web路由处理程序知道预先计算的重对象,这是计算result

最后,我打算做的是避免my_big_heavy_object每次请求出现时都必须重新计算,而是一劳永逸地计算它main,从index方法中访问它。

extern crate actix_web;
use actix_web::{server, App, HttpRequest};

fn index(_req: HttpRequest) -> HttpResponse {
    // how can I access my_big_heavy_object from here?
    let result = do_something_with(my_big_heavy_object);
    HttpResponse::Ok()
        .content_type("application/json")
        .body(result)
}

fn main() {
    let my_big_heavy_object = compute_big_heavy_object();

    server::new(|| App::new().resource("/", |r| r.f(index)))
        .bind("127.0.0.1:8088")
        .unwrap()
        .run();
}
4

1 回答 1

2

首先,创建一个结构,它是您的应用程序的共享状态:

struct AppState {
    my_big_heavy_object: HeavyObject,
}

最好像这样创建一个上下文包装器,而不是仅仅使用HeavyObject,因此您可以稍后在必要时向其中添加其他字段。

Actix 中的一些对象现在需要与之交互,因此您可以通过覆盖这些类型中的应用程序状态参数来让它们知道它,例如HttpRequest<AppState>.

您的index处理程序可以通过HttpRequest'state属性访问状态,现在看起来像这样:

fn index(req: HttpRequest<AppState>) -> HttpResponse {
    let result = do_something_with(req.state.my_big_heavy_object);
    HttpResponse::Ok()
        .content_type("application/json")
        .body(result)
}

构建时App,使用with_state构造函数而不是new

server::new(|| {
        let app_state = AppState { my_big_heavy_object: compute_big_heavy_object() };
        App::with_state(app_state).resource("/", |r| r.f(index))
    })
    .bind("127.0.0.1:8088")
    .unwrap()
    .run();

请注意,假定应用程序状态是不可变的。听起来你不需要任何处理程序来改变它,但如果你这样做了,那么你将不得不使用类似Cellor的东西RefCell来实现内部可变性。

于 2018-06-12T15:15:07.747 回答