Rust + Axum + Diesel 构建高性能 Todo API 全程指南

作者:API传播员 · 2025-11-02 · 阅读时间:6分钟
本文详细介绍了如何使用Rust语言结合Axum框架和Diesel ORM构建高性能的Todo应用程序RESTful API。通过逐步指南,包括项目初始化、数据库迁移设置、Axum服务器实现以及完整的CRUD操作处理程序,展示了Rust在Web开发中的高性能和内存安全优势。

一、背景:为什么用 Rust 写 Web API?

在现代 Web 开发 中,性能与安全性至关重要。Rust 作为一门强调速度和内存安全的系统编程语言,已经成为构建高性能 Web 应用程序的理想选择。本文将一步步介绍如何使用 Rust + Axum + Diesel 构建一个遵循 RESTful 原则的 Todo API,并实现 CRUD、连接池、错误处理等生产级功能。


二、项目初始化与依赖管理

1. 创建项目并添加依赖

cargo new rust-todo-api && cd rust-todo-api
cargo add axum tokio -F full
cargo add diesel -F postgres
cargo add serde -F derive
cargo add r2d2        # 连接池

💡 AI 助攻
想自动生成带注释的 Cargo.toml?用「代码生成」提示词,30 秒即可拿到模板,再交给「代码优化」移除冗余特性,编译速度提升 20%!


三、数据库迁移与 Schema 生成

1. 安装 Diesel CLI 并初始化

cargo install diesel_cli --no-default-features -F postgres
diesel setup              # 创建 migrations 目录与 diesel.toml
diesel migration generate create_todos

2. 编写迁移文件

migrations/2023-xx-xx_create_todos/up.sql

CREATE TABLE todos (
  id SERIAL PRIMARY KEY,
  title TEXT NOT NULL,
  completed BOOLEAN NOT NULL DEFAULT FALSE
);

down.sql

DROP TABLE todos;

3. 应用迁移并生成 schema

diesel migration run      # 生成 src/schema.rs

四、构建 Axum HTTP 服务器

1. 主函数与路由汇总

// src/main.rs
use axum::{
    routing::{get, post, put, delete},
    Router, Extension, Json, http::StatusCode,
};
use diesel::pg::PgConnection;
use diesel::r2d2::{self, ConnectionManager};
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;

type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;

#[tokio::main]
async fn main() {
    let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    let pool = r2d2::Pool::builder()
        .build(manager)
        .expect("Failed to create pool.");

    let app = Router::new()
        .route("/todos", get(get_todos).post(create_todo))
        .route("/todos/:id", put(update_todo).delete(delete_todo))
        .layer(Extension(pool));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

🔍 AI 审查
把「连接池配置」提交评审?「代码审查助手」可自动检查最大连接数、超时设置,提前发现 80% 性能隐患!


五、CRUD 处理程序实现

1. 共享模型与 DTO

#[derive(Serialize, Deserialize)]
struct NewTodo {
    title: String,
}

#[derive(Serialize, Deserialize)]
struct UpdateTodo {
    title: Option<String>,
    completed: Option<bool>,
}

2. 创建 Todo

async fn create_todo(
    Extension(pool): Extension<DbPool>,
    Json(new_todo): Json<NewTodo>,
) -> impl IntoResponse {
    let conn = pool.get().expect("pool error");
    let todo = diesel::insert_into(schema::todos::table)
        .values(&new_todo.title)
        .get_result::<Todo>(&conn)
        .expect("insert error");
    (StatusCode::CREATED, Json(todo))
}

3. 查询列表

async fn get_todos(Extension(pool): Extension<DbPool>) -> impl IntoResponse {
    let conn = pool.get().expect("pool error");
    let results = schema::todos::table.load::<Todo>(&conn).expect("select error");
    Json(results)
}

4. 更新与删除

async fn update_todo(
    Extension(pool): Extension<DbPool>,
    Path(id): Path<i32>,
    Json(update): Json<UpdateTodo>,
) -> impl IntoResponse {
    let conn = pool.get().expect("pool error");
    diesel::update(schema::todos::table.find(id)))
        .set(&update)
        .execute(&conn)
        .expect("update error");
    StatusCode::OK
}

async fn delete_todo(
    Extension(pool): Extension<DbPool>,
    Path(id): Path<i32>,
) -> impl IntoResponse {
    let conn = pool.get().expect("pool error");
    diesel::delete(schema::todos::table.find(id)))
        .execute(&conn)
        .expect("delete error");
    StatusCode::NO_CONTENT
}

六、运行与测试

1. 启动服务

export DATABASE_URL=postgres://user:pass@localhost/todo_db
cargo run

2. 快速验证(curl)

# 创建
curl -X POST localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"Learn Rust"}'

# 列表
curl localhost:3000/todos

# 更新
curl -X PUT localhost:3000/todos/1 \
  -H "Content-Type: application/json" \
  -d '{"completed":true}'

# 删除
curl -X DELETE localhost:3000/todos/1

AI 补救
把「curl 测试命令」写进 README 太麻烦?用「代码文档生成器」提示词,自动在函数头部生成标准注释,提醒后续接入 Postman 集合,文档一键达标!


七、进阶路线

  1. 错误统一处理:使用 thiserror 定义业务错误 + Axum 的 IntoResponse
  2. JWT 认证:添加 axum-extraTypedHeader 验证 Bearer
  3. OpenAPI 文档:集成 utoipa 自动生成 Swagger UI
  4. Docker 化:多阶段构建,最终镜像 < 20 MB
  5. CI/CD:GitHub Actions 自动跑 cargo test + cargo clippy

八、总结与下一步

通过本文的逐步指南,我们成功使用 Rust、Axum 和 Diesel 构建了一个功能齐全的 Todo API,涵盖:

  • 高性能连接池
  • 编译时安全的 SQL 查询
  • 模块化的 Axum 路由

未来可在此基础上添加身份验证、更复杂的查询逻辑以及其他功能,以满足实际业务需求。希望本文能为您提供启发,祝编码愉快!

🎯 立即行动
把代码 push 到 GitHub → 用 Fly.io / Render 一键部署 → 前端 React 调用,今晚就能拥有属于自己的高性能 Todo API


原文链接: https://docs.rapidapp.io/blog/building-a-todo-api-with-rust-axum-and-diesel