状态管理 #
Rocket提供了多种状态管理方式,可以在应用级别和请求级别共享数据。本节将介绍如何有效地管理应用状态。
应用状态 #
使用manage添加状态 #
rust
use std::sync::Mutex;
use std::collections::HashMap;
struct AppState {
counter: Mutex<u32>,
users: Mutex<HashMap<u32, String>>,
}
#[launch]
fn rocket() -> _ {
let state = AppState {
counter: Mutex::new(0),
users: Mutex::new(HashMap::new()),
};
rocket::build()
.manage(state)
.mount("/", routes![increment, get_count])
}
使用State获取状态 #
rust
use rocket::State;
#[get("/count")]
fn get_count(state: &State<AppState>) -> String {
let count = state.counter.lock().unwrap();
format!("Count: {}", *count)
}
#[get("/increment")]
fn increment(state: &State<AppState>) -> String {
let mut count = state.counter.lock().unwrap();
*count += 1;
format!("Count: {}", *count)
}
多状态管理 #
添加多个状态 #
rust
#[launch]
fn rocket() -> _ {
rocket::build()
.manage(DbPool::new())
.manage(Config::from_env())
.manage(Cache::new())
.mount("/", routes![get_user])
}
获取多个状态 #
rust
#[get("/user/<id>")]
fn get_user(
db: &State<DbPool>,
cache: &State<Cache>,
config: &State<Config>,
) -> String {
format!("Getting user with config: {:?}", config)
}
数据库连接池 #
简单连接池 #
rust
use std::sync::Arc;
use tokio::sync::Mutex;
pub struct DbPool {
connections: Arc<Mutex<Vec<DbConnection>>>,
}
impl DbPool {
pub fn new() -> Self {
Self {
connections: Arc::new(Mutex::new(Vec::new())),
}
}
pub async fn get_connection(&self) -> DbConnection {
DbConnection
}
}
pub struct DbConnection;
impl DbConnection {
pub async fn query(&self, sql: &str) -> Vec<String> {
vec!["result".to_string()]
}
}
使用连接池 #
rust
#[get("/users")]
async fn list_users(pool: &State<DbPool>) -> String {
let conn = pool.get_connection().await;
let users = conn.query("SELECT * FROM users").await;
format!("Users: {:?}", users)
}
配置管理 #
配置结构 #
rust
use std::env;
#[derive(Debug, Clone)]
pub struct Config {
pub database_url: String,
pub jwt_secret: String,
pub server_port: u16,
pub debug: bool,
}
impl Config {
pub fn from_env() -> Self {
Self {
database_url: env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://localhost/mydb".to_string()),
jwt_secret: env::var("JWT_SECRET")
.unwrap_or_else(|_| "secret".to_string()),
server_port: env::var("PORT")
.map(|p| p.parse().unwrap_or(8000))
.unwrap_or(8000),
debug: env::var("DEBUG")
.map(|d| d == "true")
.unwrap_or(false),
}
}
}
使用配置 #
rust
#[get("/config")]
fn show_config(config: &State<Config>) -> String {
format!("Running on port {}, debug: {}", config.server_port, config.debug)
}
缓存管理 #
内存缓存 #
rust
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use std::time::{Duration, Instant};
pub struct Cache {
data: Arc<RwLock<HashMap<String, CacheEntry>>>,
}
struct CacheEntry {
value: String,
expires_at: Instant,
}
impl Cache {
pub fn new() -> Self {
Self {
data: Arc::new(RwLock::new(HashMap::new())),
}
}
pub async fn get(&self, key: &str) -> Option<String> {
let data = self.data.read().await;
data.get(key)
.filter(|entry| entry.expires_at > Instant::now())
.map(|entry| entry.value.clone())
}
pub async fn set(&self, key: String, value: String, ttl: Duration) {
let mut data = self.data.write().await;
data.insert(key, CacheEntry {
value,
expires_at: Instant::now() + ttl,
});
}
pub async fn delete(&self, key: &str) {
let mut data = self.data.write().await;
data.remove(key);
}
}
使用缓存 #
rust
use std::time::Duration;
#[get("/cached/<key>")]
async fn get_cached(key: &str, cache: &State<Cache>) -> String {
match cache.get(key).await {
Some(value) => format!("Cached: {}", value),
None => {
let value = format!("value-for-{}", key);
cache.set(key.to_string(), value.clone(), Duration::from_secs(60)).await;
format!("New: {}", value)
}
}
}
请求本地状态 #
使用local_cache #
rust
use rocket::request::Request;
#[get("/compute")]
fn compute(request: &Request<'_>) -> String {
let result = request.local_cache(|| {
expensive_computation()
});
format!("Result: {}", result)
}
fn expensive_computation() -> String {
"computed-value".to_string()
}
完整示例 #
rust
#[macro_use] extern crate rocket;
use rocket::State;
use std::sync::Mutex;
use std::collections::HashMap;
use std::time::{Duration, Instant};
use tokio::sync::RwLock;
#[derive(Debug, Clone)]
struct Config {
app_name: String,
version: String,
}
struct Cache {
data: RwLock<HashMap<String, (String, Instant)>>,
}
impl Cache {
fn new() -> Self {
Self {
data: RwLock::new(HashMap::new()),
}
}
async fn get(&self, key: &str) -> Option<String> {
let data = self.data.read().await;
data.get(key)
.filter(|(_, expires)| expires > &Instant::now())
.map(|(value, _)| value.clone())
}
async fn set(&self, key: String, value: String, ttl: Duration) {
let mut data = self.data.write().await;
data.insert(key, (value, Instant::now() + ttl));
}
}
struct Db {
users: Mutex<HashMap<u32, User>>,
}
#[derive(Debug, Clone, rocket::serde::Serialize, rocket::serde::Deserialize)]
#[serde(crate = "rocket::serde")]
struct User {
id: u32,
name: String,
email: String,
}
impl Db {
fn new() -> Self {
let mut users = HashMap::new();
users.insert(1, User { id: 1, name: "Alice".to_string(), email: "alice@example.com".to_string() });
users.insert(2, User { id: 2, name: "Bob".to_string(), email: "bob@example.com".to_string() });
Self {
users: Mutex::new(users),
}
}
fn get_user(&self, id: u32) -> Option<User> {
let users = self.users.lock().unwrap();
users.get(&id).cloned()
}
fn create_user(&self, user: User) -> User {
let mut users = self.users.lock().unwrap();
let id = users.len() as u32 + 1;
let user = User { id, ..user };
users.insert(id, user.clone());
user
}
fn list_users(&self) -> Vec<User> {
let users = self.users.lock().unwrap();
users.values().cloned().collect()
}
}
#[get("/")]
fn index(config: &State<Config>) -> String {
format!("{} v{}", config.app_name, config.version)
}
#[get("/users")]
fn list_users(db: &State<Db>) -> rocket::serde::json::Json<Vec<User>> {
rocket::serde::json::Json(db.list_users())
}
#[get("/users/<id>")]
async fn get_user(id: u32, db: &State<Db>, cache: &State<Cache>) -> Option<rocket::serde::json::Json<User>> {
let cache_key = format!("user:{}", id);
if let Some(cached) = cache.get(&cache_key).await {
println!("Cache hit for user {}", id);
}
db.get_user(id).map(rocket::serde::json::Json)
}
#[post("/users", format = "json", data = "<user>")]
fn create_user(user: rocket::serde::json::Json<User>, db: &State<Db>) -> rocket::serde::json::Json<User> {
let created = db.create_user(user.into_inner());
rocket::serde::json::Json(created)
}
#[launch]
fn rocket() -> _ {
rocket::build()
.manage(Config {
app_name: "Rocket API".to_string(),
version: "1.0.0".to_string(),
})
.manage(Db::new())
.manage(Cache::new())
.mount("/api", routes![index, list_users, get_user, create_user])
}
下一步 #
掌握了状态管理后,让我们继续学习 数据库概述,了解Rocket与数据库的集成方式。
最后更新:2026-03-28