如何在30分钟内用Rust编写REST API:初学者指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:为什么用Rust开发REST API?

Rust是一种现代系统编程语言,兼具C++的性能和内存安全性。近年来,它已成为构建高负载Web服务的热门选择。如果你已经熟悉Python并想尝试新事物,Rust将是一个绝佳的进阶选择。

在本文中,我们将使用Actix-web框架,用Rust创建一个功能完整的任务管理(Todo List)REST API。按照指南操作,整个过程不超过30分钟。



1. 环境准备

安装Rust

如果你尚未安装Rust,请在终端(Linux/macOS)中执行以下命令:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

对于Windows,请从官方网站下载安装程序。

安装后检查版本:

rustc --version


创建项目

使用Cargo(Rust的包管理器)创建一个新项目:

cargo new rust_todo_apicd rust_todo_api


添加依赖

打开Cargo.toml文件,添加以下依赖:

[dependencies]actix-web = "4"actix-rt = "2"serde = { version = "1", features = ["derive"] }serde_json = "1"tokio = { version = "1", features = ["full"] }

保存文件。首次构建时,Cargo会自动下载所有库。



2. 创建数据模型和存储

在编写端点之前,先定义数据结构。我们将使用内存中的简单向量(用于演示)。



任务模型

创建文件src/models.rs:

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone)]pub struct Task { pub id: u32, pub title: String, pub completed: bool,}


全局存储

在src/main.rs中添加全局状态。为了线程安全,使用Mutex:

use std::sync::Mutex;use actix_web::{web, App, HttpServer, HttpResponse, HttpRequest, Responder};use models::Task;

mod models;

struct AppState { tasks: Mutex<Vec<Task>>, next_id: Mutex<u32>,}


3. 实现CRUD端点

现在编写主要的处理函数。它们都将通过web::Data接收应用状态。



GET /tasks — 获取所有任务

async fn get_tasks(data: web::Data<AppState>) -> impl Responder {    let tasks = data.tasks.lock().unwrap();    HttpResponse::Ok().json(tasks.clone())}


POST /tasks — 创建新任务

async fn create_task(data: web::Data<AppState>, body: web::Json<Task>) -> impl Responder {    let mut tasks = data.tasks.lock().unwrap();    let mut next_id = data.next_id.lock().unwrap();    let new_task = Task {        id: *next_id,        title: body.title.clone(),        completed: false,    };    tasks.push(new_task.clone());    *next_id += 1;    HttpResponse::Created().json(new_task)}


GET /tasks/{id} — 根据ID获取任务

async fn get_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {    let id = path.into_inner();    let tasks = data.tasks.lock().unwrap();    match tasks.iter().find(|t| t.id == id) {        Some(task) => HttpResponse::Ok().json(task),        None => HttpResponse::NotFound().json("Task not found"),    }}


DELETE /tasks/{id} — 删除任务

async fn delete_task(data: web::Data<AppState>, path: web::Path<u32>) -> impl Responder {    let id = path.into_inner();    l                

博客

书籍推荐