Rust + Rocket + Diesel 构建 REST API 全程指南

作者:API传播员 · 2025-11-03 · 阅读时间:8分钟
本文详细介绍了如何使用Rust的Rocket框架和Diesel ORM创建REST API。Rust以其内存安全性和高效性著称,通过所有权机制避免内存泄漏。Rocket简化了Web应用开发,而Diesel提供了与关系型数据库的交互能力。文章包含从项目初始化、数据库迁移到API实现的完整步骤,适合希望利用Rust构建高性能Web服务的开发者。

一、Rust 优势速览

  • 性能:接近 C 的执行速度,零成本抽象
  • 内存安全:所有权模型编译期杜绝空指针/悬垂指针
  • 无 GC:适合后端、嵌入式、CLI 等多场景
  • 工具链:Cargo 一键管理依赖、构建、测试、文档

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


二、技术栈选型

组件 用途 版本
Rocket Web 框架 0.4.x
Diesel ORM & 查询构建器 1.4.x
PostgreSQL 关系型数据库 14+
Serde JSON 序列化 1.0
BCrypt 密码哈希 0.10

三、项目初始化与结构

cargo new hello-rocket-bin --bin
cd hello-rocket-bin

Cargo.toml 关键依赖:

[dependencies]
rocket = "0.4.11"
rocket_contrib = "0.4.11"
diesel = { version = "1.4.8", features = ["postgres"] }
dotenv = "0.15.0"
serde = { version = "1.0", features = ["derive"] }
bcrypt = "0.10.0"

项目骨架:

src/
├── main.rs # Rocket 路由与启动
├── lib.rs # 模块汇总
├── schema.rs # Diesel 自动生成
├── models.rs # 实体与 JSON 映射
├── routes/ # 业务路由
└── db.rs # 数据库连接池

四、数据库迁移(PostgreSQL)

1. 安装 Diesel CLI

cargo install diesel_cli --no-default-features --features postgres

2. 配置环境变量

echo "DATABASE_URL=postgres://user:password@localhost/db_name" > .env
diesel setup

3. 创建迁移

diesel migration generate create_roles
diesel migration generate create_users

up.sql 示例:

CREATE TABLE roles (
    id SERIAL PRIMARY KEY,
    name VARCHAR NOT NULL
);

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR NOT NULL,
    role_id INTEGER REFERENCES roles(id)
);

down.sql:

DROP TABLE users;
DROP TABLE roles;

应用迁移:

diesel migration run
# 自动生成 src/schema.rs

🔍 AI 审查
把「Diesel 迁移脚本」提交评审?「代码审查助手」可自动检查 SQL 注入、字段冗余,提前发现 80% 潜在 Bug!


五、定义模型与模式

// src/models.rs
use serde::{Deserialize, Serialize};
use crate::schema::{roles, users};

#[derive(Queryable, Serialize)]
pub struct Role {
    pub id: i32,
    pub name: String,
}

#[derive(Insertable, Deserialize)]
#[table_name = "roles"]
pub struct NewRole {
    pub name: String,
}

#[derive(Queryable, Serialize)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub role_id: i32,
}

#[derive(Insertable, Deserialize)]
#[table_name = "users"]
pub struct NewUser {
    pub name: String,
    pub role_id: i32,
}

六、数据库连接池

// src/db.rs
use rocket::request::Request;
use rocket::response::Response;
use rocket::fairing::{Fairing, Info, Kind};
use diesel::pg::PgConnection;
use diesel::prelude::*;
use r2d2_diesel::ConnectionManager;
use r2d2::{Pool, PooledConnection};

type PgPool = Pool<ConnectionManager<PgConnection>>;

pub struct DbConn(pub PooledConnection<ConnectionManager<PgConnection>>);

impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
    type Error = ();
    fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> {
        let pool = request.guard::<State<PgPool>>()?;
        match pool.get() {
            Ok(conn) => Outcome::Success(DbConn(conn)),
            Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
        }
    }
}

七、CRUD 路由实现

1. 新增角色

#[post("/roles", format = "json", data = "<new_role>")]
fn create_role(new_role: Json<NewRole>, conn: DbConn) -> Json<Value> {
    let role = conn.run(|c| {
        diesel::insert_into(roles::table)
            .values(&new_role.into_inner())
            .get_result::<Role>(c)
            .expect("Error saving role")
    });
    json!({ "id": role.id, "name": role.name })
}

2. 新增用户

#[post("/users", format = "json", data = "<new_user>")]
fn create_user(new_user: Json<NewUser>, conn: DbConn) -> Json<Value> {
    let user = conn.run(|c| {
        diesel::insert_into(users::table)
            .values(&new_user.into_inner())
            .get_result::<User>(c)
            .expect("Error saving user")
    });
    json!({ "id": user.id, "name": user.name, "role_id": user.role_id })
}

3. 查询所有用户

#[get("/users")]
fn get_users(conn: DbConn) -> Json<Value> {
    let users = conn.run(|c| {
        users::table
            .inner_join(roles::table)
            .load::<(User, Role)>(c)
            .expect("Error loading users")
    });
    json!(users)
}

4. 更新用户信息

#[put("/users/<id>", format = "json", data = "<user>")]
fn update_user(id: i32, user: Json<NewUser>, conn: DbConn) -> Json<Value> {
    conn.run(|c| {
        diesel::update(users::table.find(id)))
            .set(&user.into_inner())
            .execute(c)
            .expect("Error updating user");
    });
    json!({ "status": "success", "id": id })
}

5. 删除用户

#[delete("/users/<id>")]
fn delete_user(id: i32, conn: DbConn) -> Json<Value> {
    conn.run(|c| {
        diesel::delete(users::table.find(id)))
            .execute(c)
            .expect("Error deleting user");
    });
    json!({ "status": "success", "id": id })
}

八、启动与测试

1. 启动服务

cargo run
# 默认监听 localhost:8000

2. 快速验证(curl)

# 新增角色
curl -X POST localhost:8000/roles \
  -H "Content-Type: application/json" \
  -d '{"name":"admin"}'

# 新增用户
curl -X POST localhost:8000/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","role_id":1}'

# 查询用户列表
curl localhost:8000/users

# 更新用户
curl -X PUT localhost:8000/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice Smith","role_id":1}'

# 删除用户
curl -X DELETE localhost:8000/users/1

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


九、进阶路线图

阶段 技术点 工具/库
① 认证 JWT + Rocket 中间件 rocket-jwt
② 分页 limit/offset 查询 diesel-pagination
③ 日志 结构化日志 tracing
④ 容器化 多阶段构建 Docker
⑤ CI/CD GitHub Actions cargo test + clippy

十、总结与下一步

通过本教程,您已学会:

  • 使用 Rocket 定义 REST 端点
  • 使用 Diesel 进行类型安全的 CRUD
  • PostgreSQL 迁移与连接池管理
  • JSON 自动序列化/反序列化

下一步可在此基础上添加认证、分页、OpenAPI 文档等功能,打造生产级后端。祝编码愉快!

今晚就 push 到 GitHub,明天就能用 Fly.io 一键部署!🚀


原文链接: https://www.workfall.com/learning/blog/how-to-create-a-rest-api-with-rust-rocket-framework-and-diesel-middleware-with-postgresql-database/