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

发布于:2025-07-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

基于 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())
    

网站公告

今日签到

点亮在社区的每一天
去签到