Depot
Depot 是用于保存一次请求中涉及到的临时数据. 中间件可以将自己处理的临时数据放入 Depot, 供后续程序使用.
当一个服务器接收到一个客户浏览器发来的请求后会创建一个 Depot 的实例. 这个实例会在所有的中间件和 Handler 处理完请求后被销毁.
比如说, 我们可以在登录的中间件中设置 current_user, 然后在后续的中间件或者 Handler 中读取当前用户信息.
快速理解
Depot 用于在请求处理过程中存储和共享数据。它实现了一个类型安全的数据容器,支持两种主要使用模式:
- 键值存储:通过
insert/get 方法存取字符串键关联的值
- 类型注入:通过
inject/obtain 方法基于类型存取值
如示例所示,Depot 特别适用于在中间件和处理程序之间传递数据。中间件可以在 Depot 中设置值(如用户信息、认证状态),后续处理程序可以获取这些值,无需重复计算或查询。Depot 的设计确保了在整个请求处理链中数据的一致性和可访问性,是构建复杂 Web 应用的核心工具。
use salvo::prelude::*;
#[handler]
async fn set_user(depot: &mut Depot) {
depot.insert("user", "client");
}
#[handler]
async fn hello(depot: &mut Depot) -> String {
format!(
"Hello {}",
depot.get::<&str>("user").copied().unwrap_or_default()
)
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let router = Router::new().hoop(set_user).goal(hello);
let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
Server::new(acceptor).serve(router).await;
}
[package]
name = "example-use-depot"
version.workspace = true
edition.workspace = true
publish.workspace = true
rust-version.workspace = true
[dependencies]
salvo = { workspace = true }
tokio = { workspace = true, features = ["macros"] }
tracing.workspace = true
tracing-subscriber.workspace = true
通过 insert 和 get 设置和取出数据
正如上面所示, 可以通过 insert 把 key 和 value 插入到 Depot 中. 对于这一类型的值, 直接用 get 取出.
depot.insert("a", "b");
assert_eq!(depot.get::<&str>("a").copied().unwrap(), "b")
如果不存在这个 key, 或者 key 存在, 但是类型不匹配, 则返回 None.
通过 inject 和 obtain 设置和取出数据
有时, 存在一些不需要关系具体 key, 对于这种类型也存在唯一实例的情况. 可以使用 inject 插入数据, 然后使用 obtain 取出数据. 它们不需要你提供 key.
depot.inject(Config::new());
depot.obtain::<Config>();
Depot 结构体方法概览