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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90448.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90448.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90448.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springMVC01-特点、创建项目、@RequestMapping、获取参数请求,三种域对象

一、简介 SpringMVC 就是 Spring 框架中的 MVC 模块&#xff0c;用于构建 Web 应用中的“控制层”。 SpringMVC 是 Spring 提供的一个基于 Servlet 的 Web MVC 框架模块&#xff0c;是 Spring 整个体系中的“Web 层核心”。 SpringMVC 是 Spring 的一部分&#xff0c;Spring…

Java基础,反射破坏封装性 - 单例模式的崩塌

目录一、容易出现问题的小李代码小李的单例设计看似完美&#xff0c;实则存在三个致命问题&#xff1a;1、反射攻击的天然漏洞2、序列化的隐患3、性能瓶颈二、隔壁老王的优化方案三、为什么这样优化&#xff1f;四、小结周五下午&#xff0c;代码审查会议上&#xff0c;小李自信…

Neo4j 综合练习作业

Neo4j 综合练习作业 作业说明 这个作业涵盖了 Neo4j 的多个重要知识点&#xff0c;包括节点和关系的创建、查询、更新、删除以及高级查询功能。请使用 Cypher 语句完成以下所有题目。 数据准备 首先执行以下语句创建示例数据&#xff1a; ACTED_IN: 表示出演关系 DIRECTED: 表示…

基于PA算法的FTL引导

一、抽象绑定关系 1. 什么是 AF Block,什么是 NF Block,为什么要将多个 NF Block 绑定为一个 AF Block AF Block(Allocation Flash Block) 和 NF Block(NAND Flash Block) 是在 NAND Flash 存储架构中用于管理数据的基本单位。 AF Block 定义:AF Block 是一组多个 NF…

快速入门Java中的IO操作

以下是 Java 中常用的 IO 知识点总结&#xff1a; 1. 流的分类 按数据流向&#xff1a;输入流&#xff08;读取数据&#xff09;和输出流&#xff08;写入数据&#xff09;。按数据类型&#xff1a;字节流&#xff08;处理二进制数据&#xff0c;以字节为单位&#xff09;和字符…

小程序软装: 组件库开发

本节概述 经过前面小节的学习&#xff0c;我们已经搭建起了小程序的编译构建环境&#xff0c;能够将我们开发的小程序项目编译成为对应的逻辑代码文件 logic.js&#xff0c;页面渲染文件 view.js&#xff0c;样式文件 style.css 和配置文件 config.json 在编译小程序的过程中…

250708-Debian系统安装Edge浏览器并配置最小中文输入法

在 Debian 系统上安装 Microsoft Edge 浏览器可以通过以下几种方式进行。Microsoft 官方提供了 .deb 安装包&#xff0c;适用于 Debian、Ubuntu 及其衍生系统。 A. 如何安装&#xff1f; ✅ 方法一&#xff1a;使用 .deb 安装包&#xff08;推荐&#xff09; 步骤 1&#xff…

docker所占硬盘内存指令

使用下面命令可以查看docker所占的硬盘大小&#xff0c;如&#xff1a;docker system dfdocker system df -v

A1126LLHLX-T Allegro霍尔效应锁存器,5kHz+推挽输出,汽车级转速检测专家!

A1126LLHLX-T&#xff08;Allegro&#xff09;产品解析一、产品定位A1126LLHLX-T是Allegro MicroSystems推出的全极性霍尔效应锁存器&#xff0c;采用超薄SOT-23W封装&#xff08;1mm厚度&#xff09;&#xff0c;专为高可靠性位置检测与转速测量设计&#xff0c;具有低功耗、高…

【C#】File从后往前读取文件指定行数

/// <summary>/// 从后往前读取文件最后行数据/// </summary>/// <param name"filePath"></param>/// <param name"count"></param>/// <returns></returns>public static List<string> ReadFileRe…

暑假算法日记第五天

目标​&#xff1a;刷完灵神专题训练算法题单 阶段目标&#x1f4cc;&#xff1a;【算法题单】滑动窗口与双指针 LeetCode题目:683. K 个关闭的灯泡2067. 等计数子串的数量2524. 子数组的最大频率分数2269. 找到一个数字的 K 美丽值1984. 学生分数的最小差值1461. 检查一个字符…

【05】MFC入门到精通——MFC 为对话框中的控件添加变量 和 数据交换和检验

文章目录四、 为对话框中的控件添加变量五、对话框类的5.1 为编辑框添加变量面步骤中 为对话框添加了几个控件&#xff0c;包括三个静态文本框&#xff0c;三个编辑框&#xff0c;一个按钮控件。 四、 为对话框中的控件添加变量 编辑框中的数据可能会经常变化&#xff0c;有必…

4-Kafka-partition(分区)概念

Kafka Topic 分区详解 &#x1f4cc; 一、分区核心概念 1. 什么是分区&#xff1f; 物理分片&#xff1a;Topic 被划分为多个分区&#xff08;Partition&#xff09;&#xff0c;每个分区是一个有序、不可变的消息序列存储单位&#xff1a;每个分区对应一个物理日志文件&…

论文略读:UniPELT: A Unified Framework for Parameter-Efficient Language Model Tuning

ACL 2021 LoRAPrefix TuningAdapter门控蓝色参数是可训练的参数

【论文阅读】CogView: Mastering Text-to-Image Generation via Transformers

CogView&#xff1a;通过Transformers实现文本到图像的生成简介目标&#xff1a;通用领域中的文本到图像生成一直是一个开放的问题&#xff0c;它既需要强大的生成模型&#xff0c;也需要跨模态的理解。为了解决这个问题&#xff0c;我们提出了CogView&#xff0c;一个具有VQ -…

Typecho与WordPress技术架构深度对比:从LAMP到轻量级设计

文章目录 Typecho vs WordPress:深入比较两大博客系统的优劣与选型指南引言1. 系统概述与技术架构1.1 WordPress架构分析1.2 Typecho架构特点2. 核心功能对比2.1 内容管理能力2.2 主题与模板系统3. 性能与扩展性对比3.1 系统性能基准测试3.2 扩展生态系统4. 安全性与维护成本4…

CSS揭秘:8.连续的图像边框

前置知识&#xff1a;CSS 渐变&#xff0c;5. 条纹背景&#xff0c;border-image&#xff0c;基本的 CSS 动画前言 本文旨在实现图片边框效果&#xff0c;即在特定场景下让图片显示在边框而非背景区域。 一、传统实现方案 正常我们面对这样一个需求时&#xff0c;下意识会想到的…

Linux驱动学习day20(pinctrl子系统驱动大全)

一、Pinctrl作用Pinctrl(Pin Controller)&#xff1a;控制引脚引脚的枚举与命名、引脚复用、引脚配置。Pinctrl驱动一般由芯片原厂的BSP工程师来写&#xff0c;一般驱动工程师只需要在设备树中指明使用哪个引脚&#xff0c;复用为哪个功能、配置为哪些状态。二、Pin Controller…

Debiased All-in-one Image Restoration with Task Uncertainty Regularization

Abstract 一体化图像恢复是一项基础的底层视觉任务&#xff0c;在现实世界中有重要应用。主要挑战在于在单个模型中处理多种退化情况。虽然当前方法主要利用任务先验信息来指导恢复模型&#xff0c;但它们通常采用统一的多任务学习&#xff0c;忽略了不同退化任务在模型优化中的…

逆向 qq 音乐 sign,data, 解密 response 返回的 arraybuffer

解密 arraybuffer python requests 请求得到 arraybuffer&#xff0c;转为 hex 传递给 js res_data sign ctx.call("decrypt", response.content.hex())function decrypt(hex) {const bytes new Uint8Array(hex.length / 2);for (let i 0; i < hex.length; i …