一、概述
Actix Web 提供了强大的应用状态管理机制,让你能够在整个应用范围内安全地共享数据。
核心状态管理方式:
应用状态会被同一作用域内的所有路由和资源共享,可以通过 web::Data<T> 提取器来访问,其中 T 代表状态数据的类型。
二、共享状态(App Data)
修改主代码 src/main.rs
use actix_web::{web,get,post, App, HttpResponse, HttpServer};
use std::sync::Mutex;
struct AppState {
counter: Mutex<i32>,
app_name: String,
}
#[get("/count")]
async fn get_count(data: web::Data<AppState>) -> HttpResponse {
let count = data.counter.lock().unwrap();
HttpResponse::Ok().json(serde_json::json!({
"app": data.app_name,
"count": *count
}))
}
#[post("/increment")]
async fn increment(data: web::Data<AppState>) -> HttpResponse {
let mut count = data.counter.lock().unwrap();
*count += 1;
HttpResponse::Ok().json(serde_json::json!({
"new_count": *count
}))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
log::info!("Starting HTTP server on http://127.0.0.1:8080");
let app_state = web::Data::new(AppState {
counter: Mutex::new(0),
app_name: String::from("Actix-Web Demo"),
});
HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.service(get_count)
.service(increment)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
测试运行,访问接口: http://127.0.0.1:8080/count

使用postman调用post接口:http://127.0.0.1:8080/increment

三、数据库连接池
这里以mysql 8为例,来演示如何连接数据库。
数据库在阿里云上面,创建一个测试数据库
CREATE DATABASE rust_blog
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
新建表users
CREATE TABLE `users` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
插入2条数据
INSERT INTO `rust_blog`.`users` (`id`, `username`, `password`, `email`, `create_time`) VALUES (1, 'Alice', 'e10adc3949ba59abbe56e057f20f883e', 'alice@example.com', '2025-11-26 18:24:22');
INSERT INTO `rust_blog`.`users` (`id`, `username`, `password`, `email`, `create_time`) VALUES (2, 'Bob', 'e10adc3949ba59abbe56e057f20f883e', 'bob@example.com', '2025-11-26 18:25:45');
注意:密码使用md5加密
修改Cargo.toml,增加mysql模块
# 异步 MySQL 驱动,支持 8.x
sqlx = { version = "0.8", features = ["runtime-tokio-native-tls", "mysql"] }
dotenvy = "0.15" # 读取 .env
项目根目录,新增文件.env
DATABASE_URL=mysql://root:123456@localhost:3306/rust_blog
注意:如果密码带有@符号,需要进行URL-encode编码
打开在线url编码器,链接:https://www.convertstring.com/zh_CN/EncodeDecode/UrlEncode
修改主代码 src/main.rs
use actix_web::{web, App, HttpResponse, HttpServer};
use dotenvy::dotenv;
use sqlx::{mysql::MySqlPool, mysql::MySqlPoolOptions, FromRow};
use serde::Serialize;
#[derive(FromRow, Serialize)]
struct User {
id: i64, // MySQL 里 BIGINT 对应 i64
username: String,
email: String,
}
#[actix_web::get("/users")]
async fn get_users_from_db(pool: web::Data<MySqlPool>) -> HttpResponse {
let users = sqlx::query_as::<_, User>("SELECT id, username, email FROM users")
.fetch_all(pool.get_ref())
.await;
match users {
Ok(users) => HttpResponse::Ok().json(users),
Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
"error": e.to_string()
})),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
// 建立连接池
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = MySqlPoolOptions::new()
.max_connections(5)
.connect(&db_url)
.await
.expect("Failed to create MySqlPool");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.service(get_users_from_db)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
注意:这里设置的连接池大小为5,生产环境,请根据实际情况修改。
重新运行,访问:http://127.0.0.1:8080/users
显示2条用户信息

本文参考链接:https://blog.youkuaiyun.com/sinat_41617212/article/details/154069236
1295

被折叠的 条评论
为什么被折叠?



