5 分钟搭好开发环境:Rust + Axum 项目从零开始
·
5 分钟搭好开发环境:Rust + Axum 项目从零开始
摘要: 从 Rust 工具链安装到启动第一个 Axum Web 服务,手把手教学。涵盖 Cargo.toml 依赖配置、Router/Extractor/Middleware/State 四大核心概念、项目分层架构设计、cargo-watch 热加载开发,附完整可运行代码。
一、安装 Rust 全家桶
Linux / macOS
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
Windows
下载 rustup-init.exe,一路 Next。
验证安装
$ rustc --version
rustc 1.85.0 (4d91de4c4 2025-02-17)
$ cargo --version
cargo 1.85.0 (d73d2caf9 2025-01-15)
配置国内镜像(中国大陆用户)
编辑 ~/.cargo/config.toml:
[source.crates-io]
replace-with = 'ustc'
[source.ustc]
registry = "sparse+https://mirrors.ustc.edu.cn/crates.io-index/"
IDE 推荐
- VS Code +
rust-analyzer插件(免费,首选) - RustRover(JetBrains,功能最强)
- Zed(新一代高性能编辑器)
二、项目初始化
cargo new nexus-ops
cd nexus-ops
生成的结构:
nexus-ops/
├── Cargo.toml # 项目元数据 + 依赖
└── src/
└── main.rs # 入口点
编辑 Cargo.toml:
[package]
name = "nexus-ops"
version = "0.1.0"
edition = "2021"
[dependencies]
# Web 框架
axum = "0.7"
# 异步运行时
tokio = { version = "1", features = ["full"] }
# JSON 序列化
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# 日志
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# 静态文件 + CORS
tower-http = { version = "0.5", features = ["cors", "fs"] }
三、第一个 Axum 应用
// src/main.rs
use axum::{
Router,
routing::get,
response::Json,
extract::Path,
};
use serde::Serialize;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
use tracing_subscriber;
#[derive(Serialize)]
struct ApiResponse<T: Serialize> {
success: bool,
data: Option<T>,
error: Option<String>,
}
#[derive(Serialize)]
struct HealthInfo {
status: String,
version: String,
uptime_seconds: u64,
}
/// GET /api/health — 健康检查
async fn health_check() -> Json<ApiResponse<HealthInfo>> {
Json(ApiResponse {
success: true,
data: Some(HealthInfo {
status: "healthy".into(),
version: env!("CARGO_PKG_VERSION").into(),
uptime_seconds: 0,
}),
error: None,
})
}
/// GET /api/devices/:id — 获取单个设备
async fn get_device(Path(id): Path<i64>) -> Json<ApiResponse<String>> {
Json(ApiResponse {
success: true,
data: Some(format!("Device #{}", id)),
error: None,
})
}
/// GET / — 首页重定向
async fn index() -> &'static str {
"NexusOps API Server is running.\n"
}
#[tokio::main]
async fn main() {
// 初始化日志
tracing_subscriber::fmt()
.with_env_filter("nexus_ops=info,tower_http=info")
.init();
// 构建路由
let app = Router::new()
.route("/", get(index))
.route("/api/health", get(health_check))
.route("/api/devices/:id", get(get_device))
.nest_service("/static", ServeDir::new("static"))
.fallback(|| async { "404 Not Found" });
// 绑定并启动
let addr = SocketAddr::from(([0, 0, 0, 0], 8080));
tracing::info!("NexusOps server listening on http://{}", addr);
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
运行:
cargo run
# 输出:
# 2026-05-07T10:00:00.000Z INFO nexus_ops: NexusOps server listening on http://0.0.0.0:8080
测试:
# 健康检查
$ curl http://localhost:8080/api/health | jq
{
"success": true,
"data": {
"status": "healthy",
"version": "0.1.0",
"uptime_seconds": 0
},
"error": null
}
# 路径参数
$ curl http://localhost:8080/api/devices/42
{"success":true,"data":"Device #42","error":null}
四、Axum 四大核心概念
1. Router(路由器)
let app = Router::new()
.route("/api/health", get(health_check)) // GET 请求
.route("/api/devices", post(create_device)) // POST 请求
.route("/api/devices/:id", get(get_device) // 路径参数
.delete(delete_device)) // 链式组合
.nest("/api/v2", v2_router) // 嵌套路由
.merge(another_router) // 合并路由
.fallback(fallback_handler); // 404 处理
2. Extractor(提取器)
use axum::{
extract::{Path, Query, State, Json},
http::StatusCode,
};
// 路径参数: /api/devices/42
async fn handler(Path(id): Path<i64>) {}
// 查询参数: /api/devices?page=1&size=20
#[derive(Deserialize)]
struct Pagination { page: Option<i64>, size: Option<i64> }
async fn handler(Query(p): Query<Pagination>) {}
// JSON 请求体
#[derive(Deserialize)]
struct CreateDeviceReq { name: String, ip: String }
async fn handler(Json(req): Json<CreateDeviceReq>) {}
// 应用状态
async fn handler(State(state): State<Arc<AppState>>) {}
// 组合使用
async fn create_device(
State(state): State<Arc<AppState>>,
Json(req): Json<CreateDeviceReq>,
) -> Result<Json<Device>, StatusCode> {
// 验证、存储、返回
}
3. State(共享状态)
use std::sync::Arc;
use rusqlite::Connection;
pub struct AppState {
pub db: Connection,
// 后面会加入更多: plugin_registry, alert_engine, ...
}
#[tokio::main]
async fn main() {
let state = Arc::new(AppState {
db: init_database(),
});
let app = Router::new()
.route("/api/devices", get(list_devices))
.with_state(state);
// ...
}
// 在 handler 中访问数据库
async fn list_devices(
State(state): State<Arc<AppState>>,
) -> Json<Vec<Device>> {
let devices = DeviceRepo::list(&state.db);
Json(devices)
}
4. Middleware(中间件)
use axum::middleware;
use tower_http::cors::{CorsLayer, Any};
let app = Router::new()
// CORS
.layer(CorsLayer::permissive())
// 请求日志
.layer(tower_http::trace::TraceLayer::new_for_http())
// 自定义鉴权中间件
.layer(middleware::from_fn(auth_middleware));
五、项目分层架构
从单文件演进到模块化结构:
src/
├── main.rs # 入口:初始化 + 启动
├── handlers/ # 请求处理层
│ ├── mod.rs
│ ├── health.rs # 健康检查
│ └── device.rs # 设备 CRUD
├── models/ # 数据模型
│ ├── mod.rs
│ ├── device.rs # 设备 struct
│ └── api.rs # 统一响应格式
├── database/ # 数据库层
│ ├── mod.rs
│ ├── migration.rs # 迁移系统
│ └── device_repo.rs # 设备数据访问
└── server/
├── mod.rs
└── routes.rs # 路由集中注册
server/routes.rs — 所有路由集中管理:
use axum::{Router, middleware};
use std::sync::Arc;
use crate::handlers;
use crate::models::AppState;
pub fn build_router(state: Arc<AppState>) -> Router {
Router::new()
.route("/api/health", get(handlers::health::check))
.route("/api/devices", get(handlers::device::list)
.post(handlers::device::create))
.route("/api/devices/:id", get(handlers::device::get)
.put(handlers::device::update)
.delete(handlers::device::delete))
.with_state(state)
}
main.rs — 入口极简:
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().init();
let state = Arc::new(AppState {
db: database::init(),
});
let app = server::routes::build_router(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
tracing::info!("Server listening on 0.0.0.0:8080");
axum::serve(listener, app).await.unwrap();
}
六、开发效率工具
cargo-watch 热加载
cargo install cargo-watch
# 文件变更自动重启
cargo watch -x run
# 仅监听 src 目录
cargo watch -w src -x run
日志调试
# 设置日志级别
RUST_LOG=nexus_ops=debug cargo run
# 按模块过滤
RUST_LOG=nexus_ops=info,axum=debug cargo run
七、常见问题
Q: 编译太慢怎么办?
# 使用 mold 链接器(Linux)
cargo install mold
# 在 .cargo/config.toml 添加:
[target.x86_64-unknown-linux-gnu]
linker = "clang"
rustflags = ["-C", "link-arg=-fuse-ld=mold"]
Q: macOS 上编译报错?
xcode-select --install # 安装命令行工具
本期要点
- Rust 工具链安装 + 国内镜像配置
- Axum 四大核心概念:Router / Extractor / State / Middleware
- 60 行代码启动一个完整的 Web 服务
- 项目分层架构:handlers / models / database / server
- cargo-watch 热加载开发
下一期预告
《SQLite 数据库设计实战:设备模型的抽象艺术》——手写数据库迁移系统、设备/接口/IP 三表设计、rusqlite 最佳实践。
完整代码:
git clone后git checkout series-ep-02
环境: Rust 1.85+, Linux/macOS/Windows
更多推荐



所有评论(0)