rust编写web服务01-项目起步与环境准备
第1堂:项目起步与环境准备
🎯 学习目标
通过本堂课,您将学会:
- 搭建Rust开发环境
- 创建Cargo项目并理解项目结构
- 选择并配置Web框架(Axum)
- 编写第一个Hello World RESTful服务
- 理解Rust模块系统的基本用法
📋 课程大纲
- Rust开发环境安装
- 框架选择与对比
- 项目创建与结构
- Hello World服务
- 模块组织基础
- 实践练习
🛠️ Rust开发环境安装
安装Rust工具链
# 安装rustup(Rust版本管理工具)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh# 或者使用Windows PowerShell
Invoke-WebRequest -Uri https://win.rustup.rs -OutFile rustup-init.exe
.\rustup-init.exe# 配置环境变量
source ~/.cargo/env# 验证安装
rustc --version
cargo --version
推荐开发工具
# 安装有用的Cargo扩展
cargo install cargo-watch # 文件变化时自动重新编译
cargo install cargo-expand # 宏展开工具
cargo install cargo-audit # 安全审计工具
🏗️ 框架选择与对比
Axum vs Actix-web
特性 | Axum | Actix-web |
---|---|---|
性能 | 极高 | 极高 |
学习曲线 | 较平缓 | 中等 |
生态系统 | 新兴但活跃 | 成熟稳定 |
异步支持 | 原生支持 | 原生支持 |
中间件 | 模块化设计 | 丰富 |
类型安全 | 极强 | 强 |
选择Axum的原因:
- 基于Tokio生态,性能优异
- 类型安全的设计理念
- 简洁的API设计
- 活跃的社区支持
📁 项目创建与结构
创建新项目
cargo new rust-web-service
cd rust-web-service
项目结构详解
rust-web-service/
├── Cargo.toml # 项目配置和依赖
├── Cargo.lock # 依赖版本锁定
├── src/ # 源代码目录
│ ├── main.rs # 程序入口
│ ├── lib.rs # 库入口
│ ├── config.rs # 配置模块
│ ├── handlers/ # 请求处理器
│ ├── models/ # 数据模型
│ ├── middleware/ # 中间件
│ └── errors.rs # 错误处理
├── migrations/ # 数据库迁移文件
├── tests/ # 测试文件
├── docs/ # 文档
└── README.md # 项目说明
Cargo.toml配置
[package]
name = "rust-web-service"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <your.email@example.com>"]
description = "A complete RESTful web service built with Rust"
license = "MIT"[dependencies]
# Web框架
axum = "0.7"
tokio = { version = "1.0", features = ["full"] }
tower = "0.4"
tower-http = { version = "0.5", features = ["cors", "fs"] }# 序列化
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"# 日志
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }# 错误处理
anyhow = "1.0"
thiserror = "1.0"# 工具
chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "1.0", features = ["v4", "serde"] }
🚀 Hello World服务
基本服务实现
// src/main.rs
use axum::{routing::get,Router,response::Json,
};
use serde_json::{json, Value};
use std::net::SocketAddr;#[tokio::main]
async fn main() {// 初始化日志tracing_subscriber::fmt::init();// 构建路由let app = Router::new().route("/", get(root)).route("/health", get(health_check)).route("/api/v1/hello", get(hello_world));// 启动服务器let addr = SocketAddr::from(([127, 0, 0, 1], 3000));println!("🚀 服务器启动在 http://{}", addr);let listener = tokio::net::TcpListener::bind(addr).await.unwrap();axum::serve(listener, app).await.unwrap();
}// 根路径处理器
async fn root() -> Json<Value> {Json(json!({"message": "欢迎来到 Rust Web 服务!","version": "1.0.0","endpoints": {"health": "/health","hello": "/api/v1/hello"}}))
}// 健康检查处理器
async fn health_check() -> Json<Value> {Json(json!({"status": "healthy","timestamp": chrono::Utc::now().to_rfc3339(),"service": "rust-web-service"}))
}// Hello World 处理器
async fn hello_world() -> Json<Value> {Json(json!({"message": "Hello, Rust Web Service! 🦀","timestamp": chrono::Utc::now().to_rfc3339(),"data": {"language": "Rust","framework": "Axum","features": ["RESTful API","JWT Authentication", "Database Integration","Redis Caching","WebSocket Support","TCP Socket Support"]}}))
}
运行服务
# 开发模式运行
cargo run# 或者使用cargo-watch自动重启
cargo watch -x run
测试API端点
# 测试根路径
curl http://localhost:3000/# 测试健康检查
curl http://localhost:3000/health# 测试Hello World
curl http://localhost:3000/api/v1/hello
🏗️ 模块组织基础
创建lib.rs
// src/lib.rs
//! Rust Web 服务库
//!
//! 这个库包含了我们的 Web 服务的所有模块和功能// 声明模块
pub mod config;
pub mod handlers;
pub mod models;
pub mod errors;// 重新导出常用的类型和函数
pub use config::AppConfig;
pub use errors::{AppError, AppResult};
创建配置模块
// src/config.rs
use serde::{Deserialize, Serialize};#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {pub server: ServerConfig,pub database: DatabaseConfig,pub redis: RedisConfig,
}#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {pub host: String,pub port: u16,
}#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseConfig {pub url: String,pub max_connections: u32,
}#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RedisConfig {pub url: String,pub max_connections: u32,
}impl Default for AppConfig {fn default() -> Self {Self {server: ServerConfig {host: "127.0.0.1".to_string(),port: 3000,},database: DatabaseConfig {url: "postgresql://localhost:5432/rust_web_service".to_string(),max_connections: 10,},redis: RedisConfig {url: "redis://localhost:6379".to_string(),max_connections: 10,},}}
}
创建错误处理模块
// src/errors.rs
use axum::{http::StatusCode,response::{IntoResponse, Response},Json,
};
use serde_json::json;
use thiserror::Error;#[derive(Error, Debug)]
pub enum AppError {#[error("数据库错误: {0}")]Database(#[from] sqlx::Error),#[error("Redis错误: {0}")]Redis(#[from] redis::RedisError),#[error("JWT错误: {0}")]Jwt(#[from] jsonwebtoken::errors::Error),#[error("验证错误: {message}")]Validation { message: String },#[error("未授权访问")]Unauthorized,#[error("资源未找到")]NotFound,#[error("内部服务器错误")]InternalServerError,
}pub type AppResult<T> = Result<T, AppError>;impl IntoResponse for AppError {fn into_response(self) -> Response {let (status, error_message) = match self {AppError::Database(_) => (StatusCode::INTERNAL_SERVER_ERROR, "数据库操作失败"),AppError::Redis(_) => (StatusCode::INTERNAL_SERVER_ERROR, "缓存操作失败"),AppError::Jwt(_) => (StatusCode::UNAUTHORIZED, "身份验证失败"),AppError::Validation { message } => (StatusCode::BAD_REQUEST, &message),AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "未授权访问"),AppError::NotFound => (StatusCode::NOT_FOUND, "资源未找到"),AppError::InternalServerError => (StatusCode::INTERNAL_SERVER_ERROR, "内部服务器错误"),};let body = Json(json!({"error": error_message,"status": status.as_u16()}));(status, body).into_response()}
}
🎯 实践练习
练习1:扩展Hello World服务
- 添加一个新的端点
/api/v1/info
,返回系统信息 - 添加请求日志中间件
- 实现优雅的错误处理
练习2:创建模块化结构
- 将处理器移动到
handlers
模块 - 创建
models
模块定义响应结构 - 使用
AppConfig
配置服务器地址和端口
练习3:添加CORS支持
use tower_http::cors::{CorsLayer, Any};let app = Router::new().route("/", get(root)).route("/health", get(health_check)).route("/api/v1/hello", get(hello_world)).layer(CorsLayer::new().allow_origin(Any).allow_methods(Any).allow_headers(Any));
📚 知识点总结
Rust核心概念
- 所有权系统: 理解move语义和借用
- 生命周期: 确保引用有效性
- 错误处理:
Result<T, E>
和?
操作符 - 异步编程:
async/await
语法
Web开发概念
- RESTful API: 资源导向的API设计
- HTTP方法: GET、POST、PUT、DELETE
- JSON: 数据序列化和反序列化
- 中间件: 请求处理管道
项目结构
- Cargo.toml: 项目配置和依赖管理
- 模块系统: 代码组织和封装
- 错误处理: 统一的错误类型和处理
🔗 相关资源
- Rust官方文档
- Axum文档
- Tokio异步运行时
- Serde序列化框架
✅ 课后作业
- 完成所有实践练习
- 阅读Rust官方书籍第1-4章
- 熟悉Cargo命令和项目结构
- 尝试修改代码,添加自己的端点
下一堂课预告: 我们将学习路由设计和请求处理,包括路径参数、查询字符串和请求体的处理。