博客系统 #
项目结构 #
text
blog-project/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── models/
│ │ ├── mod.rs
│ │ ├── user.rs
│ │ ├── post.rs
│ │ └── comment.rs
│ ├── handlers/
│ │ ├── mod.rs
│ │ ├── auth.rs
│ │ ├── post.rs
│ │ └── comment.rs
│ └── repository/
│ └── mod.rs
└── templates/
├── base.html
├── index.html
└── post.html
核心模型 #
rust
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Post {
id: u32,
title: String,
content: String,
author_id: u32,
created_at: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Comment {
id: u32,
post_id: u32,
author_id: u32,
content: String,
created_at: String,
}
#[derive(Deserialize)]
struct CreatePost {
title: String,
content: String,
}
#[derive(Deserialize)]
struct CreateComment {
content: String,
}
处理函数 #
rust
use actix_web::{web, HttpResponse, Responder};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
struct AppState {
posts: Mutex<HashMap<u32, Post>>,
comments: Mutex<HashMap<u32, Vec<Comment>>>,
next_post_id: Mutex<u32>,
next_comment_id: Mutex<u32>,
}
#[actix_web::get("/posts")]
async fn list_posts(state: web::Data<Arc<AppState>>) -> impl Responder {
let posts = state.posts.lock().unwrap();
let posts: Vec<&Post> = posts.values().collect();
HttpResponse::Ok().json(posts)
}
#[actix_web::post("/posts")]
async fn create_post(
body: web::Json<CreatePost>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let mut next_id = state.next_post_id.lock().unwrap();
let id = *next_id;
*next_id += 1;
let post = Post {
id,
title: body.title.clone(),
content: body.content.clone(),
author_id: 1,
created_at: chrono::Utc::now().to_rfc3339(),
};
state.posts.lock().unwrap().insert(id, post.clone());
HttpResponse::Created().json(post)
}
#[actix_web::get("/posts/{id}")]
async fn get_post(
path: web::Path<u32>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let posts = state.posts.lock().unwrap();
match posts.get(&path.into_inner()) {
Some(post) => HttpResponse::Ok().json(post),
None => HttpResponse::NotFound().finish(),
}
}
#[actix_web::post("/posts/{id}/comments")]
async fn add_comment(
path: web::Path<u32>,
body: web::Json<CreateComment>,
state: web::Data<Arc<AppState>>,
) -> impl Responder {
let post_id = path.into_inner();
let mut next_id = state.next_comment_id.lock().unwrap();
let id = *next_id;
*next_id += 1;
let comment = Comment {
id,
post_id,
author_id: 1,
content: body.content.clone(),
created_at: chrono::Utc::now().to_rfc3339(),
};
state.comments.lock().unwrap()
.entry(post_id)
.or_insert_with(Vec::new)
.push(comment.clone());
HttpResponse::Created().json(comment)
}
主函数 #
rust
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let state = Arc::new(AppState {
posts: Mutex::new(HashMap::new()),
comments: Mutex::new(HashMap::new()),
next_post_id: Mutex::new(1),
next_comment_id: Mutex::new(1),
});
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(state.clone()))
.service(list_posts)
.service(create_post)
.service(get_post)
.service(add_comment)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
恭喜完成! #
你已经完成了 Actix Web 框架的学习之旅!现在你已经掌握了:
- 基础入门和项目结构
- 路由系统和动态路由
- 请求处理和响应处理
- 中间件和错误处理
- 状态管理和数据库集成
- 安全特性和 WebSocket
- 测试、部署和性能优化
- 完整的实战项目
继续实践,构建更多精彩的应用!
最后更新:2026-03-29