应用状态 #
什么是应用状态? #
应用状态是在整个应用程序中共享的数据。Actix Web 通过 web::Data 提供状态管理功能。
text
┌─────────────────────────────────────────────────────────────┐
│ 应用状态架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ HttpServer │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Worker 1│ │ Worker 2│ │ Worker N│ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ App │ │ App │ │ App │ │ │
│ │ │ State │ │ State │ │ State │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 状态通过 Arc 共享,每个 Worker 有自己的 App 实例 │
│ │
└─────────────────────────────────────────────────────────────┘
基本用法 #
定义状态结构体 #
rust
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Mutex;
pub struct AppState {
pub request_count: AtomicU64,
pub users: Mutex<Vec<String>>,
}
注册状态 #
rust
use actix_web::{web, App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let state = web::Data::new(AppState {
request_count: AtomicU64::new(0),
users: Mutex::new(Vec::new()),
});
HttpServer::new(move || {
App::new()
.app_data(state.clone())
})
.bind("127.0.0.1:8080")?
.run()
.await
}
在处理函数中使用 #
rust
use actix_web::{web, Responder};
use std::sync::atomic::Ordering;
#[actix_web::get("/count")]
async fn get_count(state: web::Data<AppState>) -> impl Responder {
let count = state.request_count.load(Ordering::SeqCst);
web::Json(serde_json::json!({ "count": count }))
}
#[actix_web::post("/increment")]
async fn increment(state: web::Data<AppState>) -> impl Responder {
state.request_count.fetch_add(1, Ordering::SeqCst);
web::Json(serde_json::json!({ "success": true }))
}
状态类型 #
原子类型 #
rust
use std::sync::atomic::{AtomicU64, AtomicBool, Ordering};
pub struct AppState {
pub request_count: AtomicU64,
pub is_maintenance: AtomicBool,
}
#[actix_web::get("/status")]
async fn status(state: web::Data<AppState>) -> impl Responder {
web::Json(serde_json::json!({
"requests": state.request_count.load(Ordering::SeqCst),
"maintenance": state.is_maintenance.load(Ordering::SeqCst)
}))
}
Mutex 包装类型 #
rust
use std::sync::Mutex;
pub struct AppState {
pub cache: Mutex<std::collections::HashMap<String, String>>,
}
#[actix_web::get("/cache/{key}")]
async fn get_cache(
path: web::Path<String>,
state: web::Data<AppState>,
) -> impl Responder {
let key = path.into_inner();
let cache = state.cache.lock().unwrap();
match cache.get(&key) {
Some(value) => web::Json(serde_json::json!({ "value": value })),
None => web::Json(serde_json::json!({ "error": "Not found" })),
}
}
RwLock 包装类型 #
rust
use std::sync::RwLock;
pub struct AppState {
pub config: RwLock<Config>,
}
#[derive(Clone)]
pub struct Config {
pub debug: bool,
pub max_connections: u32,
}
#[actix_web::get("/config")]
async fn get_config(state: web::Data<AppState>) -> impl Responder {
let config = state.config.read().unwrap();
web::Json(serde_json::json!({
"debug": config.debug,
"max_connections": config.max_connections
}))
}
#[actix_web::put("/config")]
async fn update_config(
state: web::Data<AppState>,
body: web::Json<Config>,
) -> impl Responder {
let mut config = state.config.write().unwrap();
*config = body.into_inner();
web::Json(serde_json::json!({ "success": true }))
}
多个状态 #
注册多个状态 #
rust
pub struct DbPool {
// 数据库连接池
}
pub struct Cache {
// 缓存
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db_pool = web::Data::new(DbPool { /* ... */ });
let cache = web::Data::new(Cache { /* ... */ });
HttpServer::new(move || {
App::new()
.app_data(db_pool.clone())
.app_data(cache.clone())
})
.bind("127.0.0.1:8080")?
.run()
.await
}
使用多个状态 #
rust
#[actix_web::get("/users/{id}")]
async fn get_user(
path: web::Path<u32>,
db: web::Data<DbPool>,
cache: web::Data<Cache>,
) -> impl Responder {
// 使用 db 和 cache
web::Json(serde_json::json!({ "id": path.into_inner() }))
}
状态作用域 #
应用级别 #
rust
App::new()
.app_data(state) // 所有路由可用
范围级别 #
rust
App::new()
.service(
web::scope("/api")
.app_data(api_state)
.route("/users", web::get().to(get_users))
)
状态初始化 #
异步初始化 #
rust
use sqlx::postgres::PgPoolOptions;
pub struct AppState {
pub db: sqlx::PgPool,
}
impl AppState {
pub async fn new(database_url: &str) -> Self {
let db = PgPoolOptions::new()
.max_connections(5)
.connect(database_url)
.await
.expect("Failed to create pool");
Self { db }
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let database_url = std::env::var("DATABASE_URL").unwrap();
let state = web::Data::new(AppState::new(&database_url).await);
HttpServer::new(move || {
App::new()
.app_data(state.clone())
})
.bind("127.0.0.1:8080")?
.run()
.await
}
完整示例 #
rust
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
id: u64,
name: String,
email: String,
}
struct AppState {
next_id: AtomicU64,
users: Mutex<HashMap<u64, User>>,
}
impl AppState {
fn new() -> Self {
Self {
next_id: AtomicU64::new(1),
users: Mutex::new(HashMap::new()),
}
}
}
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[actix_web::get("/users")]
async fn list_users(state: web::Data<Arc<AppState>>) -> impl Responder {
let users = state.users.lock().unwrap();
let users: Vec<&User> = users.values().collect();
HttpResponse::Ok().json(users)
}
#[actix_web::get("/users/{id}")]
async fn get_user(
path: web::Path<u64>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let users = state.users.lock().unwrap();
match users.get(&path.into_inner()) {
Some(user) => HttpResponse::Ok().json(user),
None => HttpResponse::NotFound().json(serde_json::json!({
"error": "User not found"
})),
}
}
#[actix_web::post("/users")]
async fn create_user(
body: web::Json<CreateUser>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let id = state.next_id.fetch_add(1, Ordering::SeqCst);
let user = User {
id,
name: body.name.clone(),
email: body.email.clone(),
};
state.users.lock().unwrap().insert(id, user.clone());
HttpResponse::Created().json(user)
}
#[actix_web::delete("/users/{id}")]
async fn delete_user(
path: web::Path<u64>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let mut users = state.users.lock().unwrap();
match users.remove(&path.into_inner()) {
Some(_) => HttpResponse::NoContent().finish(),
None => HttpResponse::NotFound().json(serde_json::json!({
"error": "User not found"
})),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let state = Arc::new(AppState::new());
println!("Server running at http://127.0.0.1:8080");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(state.clone()))
.service(list_users)
.service(get_user)
.service(create_user)
.service(delete_user)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
下一步 #
现在你已经掌握了应用状态,继续学习 数据共享,深入了解数据共享机制!
最后更新:2026-03-29