# Rust Actix Web 入门指南
Rust Actix Web 入门指南
作者:Joshua Mo
日期:2023年12月15日
概述
- Actix Web 入门
- Actix Web 路由
- 添加数据库
- Actix Web 应用状态
- 中间件
- 静态文件服务
- 部署
- 总结
时至今日,Actix Web 仍然是 Rust Web 后端生态系统中极其强大的竞争者。尽管经历了一些事件,它依然保持强劲,成为 Rust 中最受推荐的 Web 框架之一。最初基于同名的 actor 框架(actix),现在已经脱离了原来的设计,现在 actix 主要用于 WebSocket 端点。
本文主要讨论 v4.4 版本。
Actix Web 入门
首先,使用 cargo init example-api
生成项目,然后进入项目目录,使用以下命令添加 actix-web 依赖:
cargo add actix-web
以下是基础的样板代码:
use actix_web::{web, App, HttpServer, Responder};
#[get("/")]
async fn index() -> impl Responder {
"Hello world!"
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
web::scope("/")
.route("/", web::get().to(index)),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
Actix Web 路由
在 Actix Web 中,任何返回 actix_web::Responder
特征的函数都可以作为路由。下面是一个基本的 Hello World 示例:
#[get("/")]
async fn index() -> impl Responder {
"Hello world!"
}
对于更复杂的路由配置,可以使用 ServiceConfig
:
use actix_web::{web, App, HttpResponse};
fn config(cfg: &mut web::ServiceConfig) {
cfg.service(web::resource("/test")
.route(web::get().to(|| HttpResponse::Ok()))
.route(web::head().to(|| HttpResponse::MethodNotAllowed()))
);
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().configure(config)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
提取器(Extractors)
Actix Web 提供了类型安全的请求提取器。例如,使用 JSON 提取器:
cargo add serde -F derive
use actix_web::web;
use serde::Deserialize;
#[derive(Deserialize)]
struct Info {
username: String,
}
#[post("/submit")]
async fn submit(info: web::Json<Info>) -> String {
format!("Welcome {}!", info.username)
}
支持路径、查询和表单提取:
#[derive(Deserialize)]
struct Info {
username: String,
}
#[get("/users/{username}")]
async fn index(info: web::Path<Info>) -> String {
format!("Welcome {}!", info.username)
}
#[get("/")]
async fn index(info: web::Query<Info>) -> String {
format!("Welcome {}!", info.username)
}
#[post("/")]
async fn index(form: web::Form<Info>) -> actix_web::Result<String> {
Ok(format!("Welcome {}!", form.username))
}
添加数据库
数据库连接示例:
use sqlx::PgPoolOptions;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let dbconnection = PgPoolOptions::new()
.max_connections(5)
.connect(r#"<数据库连接字符串>"#).await;
// 其余代码
}
应用状态
在 Actix Web 中共享可变状态:
use sqlx::PgPool;
#[derive(Clone)]
struct AppState {
db: PgPool
}
#[get("/")]
async fn index(data: web::Data<AppState>) -> String {
let res = sqlx::query("SELECT 'Hello World!'").fetch_all(&data.db).await.unwrap();
format!("{res}")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let db = connect_to_db();
let state = web::Data::new(AppState { db });
HttpServer::new(move || {
App::new()
.app_data(state.clone())
.route("/", web::get().to(index))
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
中间件
添加日志中间件:
use actix_web::{middleware::Logger, App};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
let app = App::new()
.wrap(Logger::default());
// 其余代码
}
静态文件服务
cargo add actix-files
use actix_files as fs;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new().service(
fs::Files::new("/static", ".")
.use_last_modified(true),
)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}
部署
使用 Shuttle 可以简化部署过程:
shuttle deploy
总结
Actix Web 是一个强大的 Rust Web 框架,非常适合构建高性能的 Web 应用。它提供了灵活的路由、强大的中间件支持,以及丰富的生态系统。