引言:为什么选择 Rust 构建 REST API?
Rust 是一种现代系统编程语言,兼具 C/C++ 的性能和内存安全性。近年来,它被广泛用于构建高负载的 Web 服务和 REST API。借助 Actix-web 框架,即使你刚刚开始学习这门语言,也可以在短短 30 分钟内用 Rust 编写一个完整的 REST API。
在本文中,我们将创建一个简单但可运行的 REST API 来管理任务列表 (Todo List)。你将学会:
- 使用 Actix-web 配置 Rust 项目
- 实现 CRUD 操作 (Create, Read, Update, Delete)
- 处理 JSON 请求和响应
- 使用路由和处理器
准备好了吗?开始吧!
步骤 1:项目配置和依赖安装
首先确保你已经安装了 Rust。如果没有,请执行以下命令:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh创建一个新项目:
cargo new rust_todo_apicd rust_todo_api打开 Cargo.toml 并添加以下依赖:
[dependencies]actix-web = "4"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"tokio = { version = "1", features = ["full"] }说明:
- actix-web — 强大的异步 Web 框架
- serde — 用于 JSON 的序列化/反序列化
- tokio — 异步运行时 (Actix-web 在底层使用它)
执行 cargo build 来下载并编译依赖。这需要 2-3 分钟。
步骤 2:创建数据模型和存储
在这个项目中,我们不会连接数据库——为简单起见,使用内存中的向量。让我们为任务创建一个结构体。
打开 src/main.rs 并编写以下代码:
use actix_web::{web, App, HttpServer, HttpResponse, middleware};use serde::{Deserialize, Serialize};use std::sync::Mutex;
// 任务模型#[derive(Serialize, Deserialize, Clone)]struct Task { id: u32, title: String, completed: bool,}
// 任务存储 (线程安全)struct AppState { tasks: Mutex<Vec<Task>>,}说明:
- #[derive(Serialize, Deserialize)] — 自动生成处理 JSON 的方法
- Mutex — 确保从多个线程安全访问数据
- AppState — 将存储在应用程序状态中
步骤 3:实现 CRUD 处理器
现在为每个 HTTP 方法添加处理器函数。在结构体声明之后插入以下代码:
// 获取所有任务async fn get_tasks(data: web::Data<AppState>) -> HttpResponse { let tasks = data.tasks.lock().unwrap(); HttpResponse::Ok().json(tasks.clone())}
// 创建新任务async fn create_task(data: web::Data<AppState>, body: web::Json<Task>) -> HttpResponse { let mut tasks = data.tasks.lock().unwrap(); let new_id = tasks.len() as u32 + 1; let task = Task { id: new_id, title: body.title.clone(), completed: body.completed, }; tasks.push(task.clone()); HttpResponse::Created().json(task)}
// 更新任务async fn update_task( data: web::Data<AppState>, path: web::Path<u32>, body: web::Json<Task>,) -> HttpResponse { let mut tasks = data.tasks.lock().unwrap(); let id = path.into_inner(); if let Some(task) = tasks.iter_mut().find(|t| t.id == id) { task.title = body.title.clone(); task.completed = body.completed; HttpRespons