15.2 使用 Axum 或 Actix-web 构建 REST API
听
在 Rust 的 Web 框架生态中,Axum 和 Actix-web 是两个主流选择,均基于 tokio 异步运行时,性能出色且社区活跃。本节将以 Axum 为主进行演示(因其与 tower 生态深度集成、API 简洁),同时简要对比 Actix-web 的差异,帮助你根据项目需求做出选择。
为什么选择 Axum?
Axum 由 Tokio 团队维护,设计理念强调:
- 基于
tower的中间件模型,兼容大量现有组件; - 利用 Rust 的类型系统提供路由安全(如路径参数类型检查);
- 与
tracing无缝集成,便于可观测性; - 无宏 DSL,使用函数和组合构建路由。
创建基本服务
首先添加依赖(Cargo.toml):
[dependencies]
axum = "0.7"
tokio = { version = "1.0", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
在 src/main.rs 中启动一个简单服务:
use axum::{routing::get, Router};
#[tokio::main]
async fn main() {
let app = Router::new().route("/health", get(health_check));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
}
async fn health_check() -> &'static str {
"OK"
}
运行后,访问 http://localhost:3000/health 将返回 "OK"。
实现任务管理 API
假设我们已定义好 Task 模型和相关 DTO(见 15.1 节),现在在 handlers/tasks.rs 中实现 CRUD 操作:
use axum::{
extract::{Path, State},
response::{IntoResponse, Response},
Json,
};
use serde::{Deserialize, Serialize};
use crate::{error::AppError, models::task::{CreateTask, Task}, services::task_service::TaskService};
pub async fn create_task(
State(service): State<TaskService>,
Json(payload): Json<CreateTask>,
) -> Result<Json<Task>, AppError> {
let task = service.create_task(payload).await?;
Ok(Json(task))
}
pub async fn get_task(
State(service): State<TaskService>,
Path(id): Path<i64>,
) -> Result<Json<Task>, AppError> {
let task = service.get_task(id).await?;
Ok(Json(task))
}
// 其他 handler 略
注意:
- 使用
State<T>提取共享应用状态(如 service); - 请求体通过
Json<T>自动反序列化; - 路径参数通过
Path<T>提取; - 错误统一由
AppError处理(见 15.5 节)。
注册路由
在 main.rs 或单独的 routes.rs 中组装路由:
use axum::Router;
use std::sync::Arc;
let shared_service = Arc::new(TaskService::new(repo));
let app = Router::new()
.route("/tasks", post(handlers::tasks::create_task))
.route("/tasks/:id", get(handlers::tasks::get_task))
.with_state(shared_service);
Axum 的 with_state 允许将任意类型注入到 handler 中,支持多状态组合(如数据库连接池 + 配置)。
与 Actix-web 的简要对比
若选择 Actix-web,代码风格略有不同:
// Actix-web 示例
use actix_web::{web, HttpResponse, Result};
async fn create_task(
payload: web::Json<CreateTask>,
service: web::Data<TaskService>,
) -> Result<HttpResponse> {
let task = service.create_task(payload.into_inner()).await?;
Ok(HttpResponse::Ok().json(task))
}
// 注册
App::new()
.app_data(web::Data::new(service))
.service(web::resource("/tasks").route(web::post().to(create_task)))
主要差异:
- Actix-web 使用
web::Data<T>注入状态; - 路由通过
App和web::resource构建; - 错误处理需实现
ResponseErrortrait。
两者性能接近,Axum 更贴近现代 Rust 的泛型和 trait 设计,而 Actix-web 文档更成熟、功能更“全栈”(如内置 WebSocket、HTTP/2 支持)。
小结
无论选择 Axum 还是 Actix-web,Rust 的 Web 框架都提供了类型安全、高性能的 API 构建能力。本节以 Axum 为例,展示了如何定义 handler、提取请求数据、注入服务依赖并组织路由。下一步,我们将把数据库集成进来,使 API 具备持久化能力。
#Rust 入门教程
分享于 5 天前
上一篇:15.1 项目架构设计
下一篇:15.3 数据库集成