实战:Todo API 服务
学习目标
- 综合 Axum + Serde + SQLx
- 实现完整 CRUD API
- 理解项目结构
项目结构
todo-api/
├── Cargo.toml
├── src/
│ ├── main.rs
│ ├── models.rs
│ ├── handlers.rs
│ └── db.rs
└── migrations/
└── 001_create_todos.sql
models.rs
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Todo {
pub id: i64,
pub title: String,
pub completed: bool,
}
#[derive(Debug, Deserialize)]
pub struct CreateTodo {
pub title: String,
}
#[derive(Debug, Deserialize)]
pub struct UpdateTodo {
pub title: Option<String>,
pub completed: Option<bool>,
}
handlers.rs
use axum::{
extract::{Path, State},
Json,
http::StatusCode,
};
use std::sync::{Arc, Mutex};
use crate::models::*;
pub type Db = Arc<Mutex<Vec<Todo>>>;
pub async fn list_todos(State(db): State<Db>) -> Json<Vec<Todo>> {
let todos = db.lock().unwrap();
Json(todos.clone())
}
pub async fn create_todo(
State(db): State<Db>,
Json(input): Json<CreateTodo>,
) -> (StatusCode, Json<Todo>) {
let mut todos = db.lock().unwrap();
let todo = Todo {
id: todos.len() as i64 + 1,
title: input.title,
completed: false,
};
todos.push(todo.clone());
(StatusCode::CREATED, Json(todo))
}
pub async fn toggle_todo(
State(db): State<Db>,
Path(id): Path<i64>,
) -> Result<Json<Todo>, StatusCode> {
let mut todos = db.lock().unwrap();
todos.iter_mut()
.find(|t| t.id == id)
.map(|t| { t.completed = !t.completed; t.clone() })
.map(Json)
.ok_or(StatusCode::NOT_FOUND)
}
main.rs
use axum::{Router, routing::{get, put}};
use std::sync::{Arc, Mutex};
mod models;
mod handlers;
#[tokio::main]
async fn main() {
let db: handlers::Db = Arc::new(Mutex::new(vec![]));
let app = Router::new()
.route("/todos", get(handlers::list_todos).post(handlers::create_todo))
.route("/todos/{id}/toggle", put(handlers::toggle_todo))
.with_state(db);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await
.unwrap();
println!("服务运行在 http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}
小结
| 技能 | 应用 |
|---|
| Axum | Web 框架 |
| Serde | JSON 序列化 |
| 共享状态 | Arc<Mutex<T>> |
| RESTful | CRUD 路由设计 |