ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于 Rust 的Actix Web 框架的应用与优化实例

基于 Rust 的Actix Web 框架的应用与优化实例

基于 Rust 的Actix Web 框架的应用与优化实例

Actix Web 框架概述

Actix Web 是一个基于 Rust 的高性能、轻量级 Web 框架,构建于 Actix 异步运行时之上。它支持异步编程模型,适合构建高并发、低延迟的 Web 服务和 API。

核心特性

  • 异步支持:基于 async/await 语法,充分利用 Rust 的异步生态。
  • 高性能:底层使用 actor 模型和零成本抽象,性能接近原生代码。
  • 类型安全:通过 Rust 的类型系统确保路由、请求和响应的安全性。
  • 灵活的路由:支持 RESTful 路由、动态路径参数和中间件。
  • WebSocket 支持:内置 WebSocket 协议支持。

基本项目结构

典型的 Actix Web 项目结构如下:

src/
├── main.rs      # 应用入口和路由配置
├── handlers.rs  # 请求处理逻辑
├── models.rs    # 数据模型
└── lib.rs       # 模块定义(可选)

快速入门示例

以下是一个最小化的 Actix Web 应用代码:

use actix_web::{get, App, HttpResponse, HttpServer, Responder};#[get("/")]
async fn hello() -> impl Responder {HttpResponse::Ok().body("Hello, Actix Web!")
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().service(hello)).bind("127.0.0.1:8080")?.run().await
}

关键组件

  1. 路由与处理函数

    • 使用 #[get]#[post] 等宏定义路由。
    • 处理函数返回 impl Responder,支持多种响应类型(如 HttpResponseString)。
  2. 状态共享
    通过 Data<T> 类型共享全局状态(如数据库连接池):

    App::new().app_data(Data::new(AppState { db: pool }))
    
  3. 中间件
    使用 wrap 添加中间件(如日志、认证):

    App::new().wrap(Logger::default())
    
  4. 错误处理
    自定义错误类型并实现 ResponseError trait:

    impl ResponseError for MyError {fn error_response(&self) -> HttpResponse {HttpResponse::InternalServerError().finish()}
    }
    

安装 Actix Web 依赖 在 Cargo.toml 中添加以下依赖:

[dependencies]
actix-web = "4"

创建基础 HTTP 服务器

use actix_web::{get, App, HttpResponse, HttpServer, Responder};#[get("/")]
async fn hello() -> impl Responder {HttpResponse::Ok().body("Hello world!")
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().service(hello)).bind(("127.0.0.1", 8080))?.run().await
}

路由处理示例

多路由配置

use actix_web::{web, App, HttpResponse, HttpServer};async fn index() -> HttpResponse {HttpResponse::Ok().body("Index page")
}async fn about() -> HttpResponse {HttpResponse::Ok().body("About page")
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| {App::new().route("/", web::get().to(index)).route("/about", web::get().to(about))}).bind(("127.0.0.1", 8080))?.run().await
}

路径参数提取

use actix_web::{get, web, App, HttpServer};#[get("/users/{user_id}/{friend}")]
async fn user_info(path: web::Path<(u32, String)>) -> String {let (user_id, friend) = path.into_inner();format!("User {}'s friend: {}", user_id, friend)
}

以下是基于Rust的路由处理示例,涵盖不同框架和场景的实用案例。示例分为基础路由、动态参数、中间件、错误处理等类别,代码均以实际可运行为目标。


基础路由(axum框架)

use axum::{Router, routing::get, Json};
use serde_json::json;async fn hello_world() -> Json<serde_json::Value> {Json(json!({ "message": "Hello, world!" }))
}#[tokio::main]
async fn main() {let app = Router::new().route("/", get(hello_world));axum::Server::bind(&"0.0.0.0:3000".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
}

动态路径参数

use axum::{Router, routing::get, extract::Path};async fn user_info(Path(user_id): Path<u32>) -> String {format!("User ID: {}", user_id)
}let app = Router::new().route("/users/:user_id", get(user_info));

查询参数处理

use axum::{Router, routing::get, extract::Query};
use serde::Deserialize;#[derive(Deserialize)]
struct Pagination {page: usize,per_page: usize,
}async fn list_items(Query(pagination): Query<Pagination>) -> String {format!("Page: {}, Per Page: {}", pagination.page, pagination.per_page)
}let app = Router::new().route("/items", get(list_items));

JSON请求体处理

use axum::{Router, routing::post, Json, extract::Extension};
use serde::{Deserialize, Serialize};#[derive(Deserialize)]
struct CreateUser {name: String,
}#[derive(Serialize)]
struct User {id: u64,name: String,
}async fn create_user(Json(input): Json<CreateUser>) -> Json<User> {Json(User { id: 1, name: input.name })
}let app = Router::new().route("/users", post(create_user));


中间件示例(日志记录)

use axum::{Router, routing::get, middleware};
use tower_http::trace::TraceLayer;async fn handler() -> &'static str { "OK" }let app = Router::new().route("/", get(handler)).layer(TraceLayer::new_for_http());

错误处理

use axum::{Router, routing::get, response::IntoResponse, http::StatusCode};async fn fallible_handler() -> Result<String, (StatusCode, &'static str)> {Err((StatusCode::INTERNAL_SERVER_ERROR, "Something went wrong"))
}let app = Router::new().route("/error", get(fallible_handler));

静态文件服务

use axum::{Router, routing::get_service};
use tower_http::services::ServeDir;let app = Router::new().nest_service("/static",get_service(ServeDir::new("./static"))
);

路由嵌套

use axum::{Router, routing::get};async fn api_v1_users() -> &'static str { "v1 users" }
async fn api_v2_users() -> &'static str { "v2 users" }let api_v1 = Router::new().route("/users", get(api_v1_users));
let api_v2 = Router::new().route("/users", get(api_v2_users));
let app = Router::new().nest("/api/v1", api_v1).nest("/api/v2", api_v2);

异步数据库操作

use axum::{Router, routing::get, Extension};
use sqlx::postgres::PgPoolOptions;async fn db_handler(Extension(pool): Extension<sqlx::PgPool>) -> String {let row: (i64,) = sqlx::query_as("SELECT $1").bind(150_i64).fetch_one(&pool).await.unwrap();format!("Result: {}", row.0)
}#[tokio::main]
async fn main() {let pool = PgPoolOptions::new().connect("postgres://user:pass@localhost/db").await.unwrap();let app = Router::new().route("/db", get(db_handler)).layer(Extension(pool));
}

WebSocket路由(axum)

use axum::{Router, routing::get, extract::ws::WebSocketUpgrade};async fn ws_handler(ws: WebSocketUpgrade) -> impl IntoResponse {ws.on_upgrade(|socket| async move {// WebSocket处理逻辑})
}let app = Router::new().route("/ws", get(ws_handler));

JSON 请求与响应

JSON 响应处理

use actix_web::{get, App, HttpServer, Responder};
use serde::Serialize;#[derive(Serialize)]
struct MyObj {name: String,age: u8,
}#[get("/json")]
async fn json_response() -> impl Responder {web::Json(MyObj {name: "Alice".to_string(),age: 30,})
}

JSON 请求处理

use actix_web::{post, web, App, HttpServer, Responder};
use serde::Deserialize;#[derive(Deserialize)]
struct Info {username: String,
}#[post("/submit")]
async fn submit(info: web::Json<Info>) -> impl Responder {format!("Welcome {}!", info.username)
}

以下是基于Rust的JSON请求与响应处理的实用示例集合,涵盖常见场景和库(如serdereqwestactix-web等)。示例按功能分类,每个示例独立可用。


基础序列化与反序列化

use serde::{Deserialize, Serialize};#[derive(Debug, Serialize, Deserialize)]
struct User {id: u32,name: String,
}// 序列化结构体到JSON字符串
let user = User { id: 1, name: "Alice".to_string() };
let json_str = serde_json::to_string(&user).unwrap();
println!("Serialized: {}", json_str); // {"id":1,"name":"Alice"}// 反序列化JSON字符串到结构体
let decoded_user: User = serde_json::from_str(&json_str).unwrap();
println!("Deserialized: {:?}", decoded_user);

使用reqwest发送GET请求

use reqwest::Error;#[tokio::main]
async fn main() -> Result<(), Error> {let response = reqwest::get("https://jsonplaceholder.typicode.com/posts/1").await?.json::<serde_json::Value>().await?;println!("Response: {:?}", response);Ok(())
}


使用reqwest发送POST请求

#[derive(Serialize)]
struct Post {title: String,body: String,userId: u32,
}#[tokio::main]
async fn main() -> Result<(), Error> {let new_post = Post {title: "Test Title".to_string(),body: "Test Body".to_string(),userId: 1,};let client = reqwest::Client::new();let res = client.post("https://jsonplaceholder.typicode.com/posts").json(&new_post).send().await?.json::<serde_json::Value>().await?;println!("Response: {:?}", res);Ok(())
}


使用actix-web处理JSON请求

use actix_web::{web, App, HttpServer, Responder};#[derive(Deserialize)]
struct Info {username: String,
}async fn greet(info: web::Json<Info>) -> impl Responder {format!("Hello {}!", info.username)
}#[actix_web::main]
async fn main() -> std::io::Result<()> {HttpServer::new(|| App::new().route("/greet", web::post().to(greet))).bind("127.0.0.1:8080")?.run().await
}


处理嵌套JSON结构

#[derive(Serialize, Deserialize)]
struct Address {street: String,city: String,
}#[derive(Serialize, Deserialize)]
struct Profile {name: String,age: u8,address: Address,
}let profile = Profile {name: "Bob".to_string(),age: 30,address: Address {street: "Main St".to_string(),city: "Metropolis".to_string(),},
};let json = serde_json::to_string_pretty(&profile).unwrap();
println!("{}", json);


自定义字段名称

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Product {product_id: u32,product_name: String,
}let product = Product {product_id: 101,product_name: "Laptop".to_string(),
};
let json = serde_json::to_string(&product).unwrap(); // {"productId":101,"productName":"Laptop"}


处理可选字段

#[derive(Serialize, Deserialize)]
struct Book {title: String,#[serde(skip_serializing_if = "Option::is_none")]subtitle: Option<String>,
}let book1 = Book { title: "Rust".to_string(), subtitle: None };
let json1 = serde_json::to_string(&book1).unwrap(); // {"title":"Rust"}let book2 = Book { title: "Rust".to_string(), subtitle: Some("Advanced".to_string()) };
let json2 = serde_json::to_string(&book2).unwrap(); // {"title":"Rust","subtitle":"Advanced"}


使用Hyper客户端

use hyper::{Client, Body};
use hyper_tls::HttpsConnector;#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {let https = HttpsConnector::new();let client = Client::builder().build::<_, Body>(https);let uri = "https://jsonplaceholder.typicode.com/todos/1".parse()?;let resp = client.get(uri).await?;let body_bytes = hyper::body::to_bytes(resp.into_body()).await?;let body_str = String::from_utf8(body_bytes.to_vec())?;println!("Response: {}", body_str);Ok(())
}


处理日期时间

use chrono::{DateTime, Utc};#[derive(Serialize, Deserialize)]
struct Event {name: String,#[serde(with = "chrono::serde::ts_seconds")]timestamp: DateTime<Utc>,
}let event = Event {name: "Conference".to_string(),timestamp: Utc::now(),
};
let json = serde_json::to_string(&event).unwrap();


使用warp框架

use warp::Filter;#[derive(Serialize, Deserialize)]
struct Message {text: String,
}let hello = warp::path("hello").and(warp::post())
返回列表