Rust 与 Postgres 构建 CRUD API 全教程
作者:API传播员 · 2025-09-23 · 阅读时间:6分钟
文章目录
编者按:本文于 2022 年 2 月 22 日更新,修复了与 Diesel 的连接问题,并进行了其他改进。
要继续本教程,你需要对 API 开发有基本了解,至少熟悉 CRUD(创建、读取、更新、删除)概念。本文将带你一步步学习如何使用 Rust 和 PostgreSQL 创建后端 API。
一. 项目要求
在开始编码之前,需要明确项目目标,并回顾完成演示所需的基本要求和假设。
我们将为一个示例员工管理应用程序创建完整的 CRUD API 端点。本项目是全新示例,旨在展示在 Rust 中编写 API 的基础构建块。
1. 需要了解的术语
本指南适合对 Rust 有基本理解的读者,以下术语需熟悉:
- Spawn blocking:用于处理繁重或长时间任务(例如从数据库中检索大量记录)。通过生成新线程,避免异步函数阻塞。
二. Rust 项目设置及结构
首先,使用 Cargo 创建 Rust 项目:
cargo new employee
1. 项目结构
项目文件夹结构如下,可根据需要调整:
employee/
├─ src/
│ └─ employees/
│ ├─ mod.rs
│ ├─ model.rs
│ ├─ routes.rs
│ ├─ db.rs
│ └─ error_handlers.rs
│ └─ main.rs
├─ .env
└─ Cargo.toml
a. mod.rs 文件
用于管理 employees 目录中模块:
mod model;
mod routes;
pub use model::*;
pub use routes::init_routes;
b. Cargo.toml 文件
项目依赖项配置:
[package]
name = "employee"
version = "0.1.0"
authors = ["Ola John"]
edition = "2018"
[dependencies]
actix-web = "3.0"
actix-rt = "1.0"
chrono = { version = "0.4", features = ["serde"] }
dotenv = "0.11"
diesel = { version = "1.4", features = ["postgres", "r2d2", "uuid", "chrono"] }
diesel_migrations = "1.4"
env_logger = "0.6"
lazy_static = "1.4"
listenfd = "0.3"
serde = "1.0"
serde_json = "1.0"
r2d2 = "0.8"
uuid = { version = "0.6", features = ["serde", "v4"] }
三. 主程序设置
主程序包含关键 crate 和配置:
actix-web 服务器设置示例:
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
dotenv().ok();
db::init();
let mut listenfd = ListenFd::from_env();
let mut server = HttpServer::new(|| App::new().configure(employees::init_routes));
server = match listenfd.take_tcp_listener(0)? {
Some(listener) => server.listen(listener)?,
None => {
let host = env::var("HOST").expect("Please set host in .env");
let port = env::var("PORT").expect("Please set port in .env");
server.bind(format!("{}:{}", host, port))?
}
};
server.run().await
}
四. 创建 API 端点
API 端点定义在 routes.rs 中。使用 serde 进行 JSON 序列化和反序列化。
#[get("/employees")]
async fn find_all() -> Result<HttpResponse, Error> {
let employees = web::block(|| Employees::find_all()).await.unwrap();
Ok(HttpResponse::Ok().json(employees))
}
#[get("/employees/{id}")]
async fn find(id: web::Path<i32>) -> Result<HttpResponse, Error> {
let employee = Employees::find(id.into_inner())?;
Ok(HttpResponse::Ok().json(employee))
}
#[post("/employees")]
async fn create(employee: web::Json<Employee>) -> Result<HttpResponse, Error> {
let employee = Employees::create(employee.into_inner())?;
Ok(HttpResponse::Ok().json(employee))
}
#[put("/employees/{id}")]
async fn update(
id: web::Path<i32>,
employee: web::Json<Employee>,
) -> Result<HttpResponse, Error> {
let employee = Employees::update(id.into_inner(), employee.into_inner())?;
Ok(HttpResponse::Ok().json(employee))
}
#[delete("/employees/{id}")]
async fn delete(id: web::Path<i32>) -> Result<HttpResponse, Error> {
let deleted_employee = Employees::delete(id.into_inner())?;
Ok(HttpResponse::Ok().json(json!({ "deleted": deleted_employee })))
}
pub fn init_routes(config: &mut web::ServiceConfig) {
config.service(find_all);
config.service(find);
config.service(create);
config.service(update);
config.service(delete);
}
五. 配置 Postgres 数据库连接
db.rs 文件示例:
use crate::error_handler::CustomError;
use diesel::pg::PgConnection;
use diesel::r2d2::ConnectionManager;
use lazy_static::lazy_static;
use r2d2;
use std::env;
type Pool = r2d2::Pool<ConnectionManager<PgConnection>>;
pub type DbConnection = r2d2::PooledConnection<ConnectionManager<PgConnection>>;
embed_migrations!();
lazy_static! {
static ref POOL: Pool = {
let db_url = env::var("DATABASE_URL").expect("Database url not set");
let manager = ConnectionManager::<PgConnection>::new(db_url);
Pool::new(manager).expect("Failed to create db pool")
};
}
pub fn init() {
lazy_static::initialize(&POOL);
let conn = connection().expect("Failed to get db connection");
embedded_migrations::run(&conn).unwrap();
}
pub fn connection() -> Result<DbConnection, CustomError> {
POOL.get()
.map_err(|e| CustomError::new(500, format!("Failed getting db connection: {}", e)))
}
六. 使用 Diesel ORM
Diesel 简化数据库查询和对象映射。
#[derive(Serialize, Deserialize, AsChangeset, Insertable)]
#[table_name = "employees"]
pub struct Employee {
pub first_name: String,
pub last_name: String,
pub department: String,
pub salary: i32,
pub age: i32,
}
#[derive(Serialize, Deserialize, Queryable)]
pub struct Employees {
pub id: i32,
pub first_name: String,
pub last_name: String,
pub department: String,
pub salary: i32,
pub age: i32,
}
七. 运行 Rust API 演示
启动项目:
cargo watch -x run
通过 API 端点,可以在数据库中执行 CRUD 操作:创建、读取、更新和删除员工记录。
八. 结论
通过本教程,你已经掌握了如何使用 Actix 在 Rust 中创建 API 端点,并处理 CRUD 操作,同时使用 Diesel 管理 Postgres 数据。
Rust 编译器确保高可靠性,成功编译几乎保证代码功能正确。这使开发过程更加高效、可维护。
原文链接: https://blog.logrocket.com/create-backend-api-with-rust-postgres/
热门推荐
一个账号试用1000+ API
助力AI无缝链接物理世界 · 无需多次注册
3000+提示词助力AI大模型
和专业工程师共享工作效率翻倍的秘密
热门API
- 1. AI文本生成
- 2. AI图片生成_文生图
- 3. AI图片生成_图生图
- 4. AI图像编辑
- 5. AI视频生成_文生视频
- 6. AI视频生成_图生视频
- 7. AI语音合成_文生语音
- 8. AI文本生成(中国)
最新文章
- 如何在 Node.js 中构建 gRPC API
- Link支付怎么注册?一站式指南
- 2025年最新图像算法面试题:图像识别、CNN算法与实战项目解析
- 如何获取 Pexels 开放平台 API Key 密钥(分步指南)
- 使用 FastAPI 和 RabbitMQ 构建端到端微服务:综合指南
- DeepSeek+dify 工作流应用,自然语言查询数据库信息并展示
- 医疗机构如何防范API漏洞威胁
- Swagger与API文档:如何使用Swagger实现API文档自动化生成
- Yahoo Finance API – 完整指南
- 使用 DEEPSEEK AI 构建应用程序:它能(和不能)做什么
- 如何获取 Figma 开放平台 API Key 密钥(分步指南)
- 大模型推理框架汇总