rust语言待办事项小实例完整代码(axum+sqlx+sqlite+自定义错误)

张开发
2026/4/17 22:52:52 15 分钟阅读

分享文章

rust语言待办事项小实例完整代码(axum+sqlx+sqlite+自定义错误)
1、Cargo.toml[dependencies] # Axum Web框架用于构建HTTP服务 axum 0.8 # Tokio异步运行时Axum的基础依赖 tokio { version 1.50, features [full] } # 数据库操作 sqlx { version 0.8, features [runtime-tokio, sqlite] } # 序列化和反序列化 serde { version 1.0, features [derive] }2、error.rs错误处理useaxum::http::StatusCode;useaxum::response::IntoResponse;// 定义我们的错误枚举pubenumAppError{// 数据库操作失败DatabaseError(sqlx::Error),// 资源未找到建议添加上下文NotFound(String)记录缺失资源名便于日志追踪NotFound,}// 实现 IntoResponse 让错误可响应// 这样 Axum 就能自动把我们的错误转成 HTTP 响应implIntoResponseforAppError{fninto_response(self)-axum::response::Response{let(status,msg)matchself{AppError::DatabaseError(_)(StatusCode::INTERNAL_SERVER_ERROR,数据库出错请稍后重试),AppError::NotFound(StatusCode::NOT_FOUND,数据不存在),};// 直接转为响应自动设置 Content-Type: text/plain; charsetutf-8(status,msg).into_response()}}// 实现从 sqlx::Error 自动转到 AppError (可以使用 “?” 操作符)// 可以实现其他错误类型的转换做到错误处理统一implFromsqlx::ErrorforAppError{fnfrom(err:sqlx::Error)-Self{AppError::DatabaseError(err)}}StatusCodeAxum 提供的 HTTP 状态码枚举如StatusCode::NOT_FOUND、StatusCode::INTERNAL_SERVER_ERROR用于标准化响应状态。IntoResponseAxum 的核心 trait任何实现了它的类型都可以直接作为路由的返回值Axum 会自动将其转换为 HTTP 响应。‌这是你自定义错误能“被框架识别”的关键‌。3、models.rs数据模型useserde::{Deserialize,Serialize};// 数据库实体#[derive(Serialize, sqlx::FromRow)]pubstructTodo{pubid:i64,pubtitle:String,// 待办事项pubcompleted:bool,// 是否弯沉}// 新增待办事项使用#[derive(Deserialize)]pubstructCreateTodo{pubtitle:String,// 待办事项}// 全局状态数据库连接池pubstructAppState{pubdb:sqlx::SqlitePool,}4、method_routers.rs路由方法usecrate::error::AppError;usecrate::models::{AppState,CreateTodo,Todo};useaxum::Json;useaxum::extract::{Path,State};useaxum::http::StatusCode;usesqlx::SqlitePool;usestd::sync::Arc;// 初始化数据库连接会在当前目录生成 todo.dbpubasyncfninit_db()-ArcAppState{// 创建数据库连接读写模式数据库不存在时创建letpoolSqlitePool::connect(sqlite:todo.db?moderwc).await.unwrap();// 创建表如果不存在sqlx::query(CREATE TABLE IF NOT EXISTS todos ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, completed BOOL NOT NULL DEFAULT 0),).execute(pool).await.unwrap();Arc::new(AppState{db:pool})}// 添加待办pubasyncfncreate_todo(State(state):StateArcAppState,Json(payload):JsonCreateTodo,)-Result(StatusCode,JsonTodo),AppError{letidsqlx::query(INSERT INTO todos (title,completed) VALUES (?,0)).bind(payload.title).execute(state.db).await?.last_insert_rowid();// 返回创建记录的idletnew_todoTodo{id,title:payload.title,completed:false,};Ok((StatusCode::CREATED,Json(new_todo)))}// 查询所有待办事项pubasyncfnlist_todos(State(state):StateArcAppState,)-Result(StatusCode,JsonVecTodo),AppError{lettodossqlx::query_as(SELECT id,title,completed FROM todos).fetch_all(state.db)// 查询全部数据.await?;Ok((StatusCode::OK,Json(todos)))}// 完成一项待办事项pubasyncfncomplete_todo(State(state):StateArcAppState,Path(id):Pathi64,)-ResultStatusCode,AppError{letresultsqlx::query(UPDATE todos SET completed 1 WHERE id ?).bind(id).execute(state.db).await?;// 修改数据影响的数据条数0时为未修改返回数据不存在ifresult.rows_affected()0{returnErr(AppError::NotFound);}Ok(StatusCode::OK)}// 删除一条待办事项pubasyncfndelete_todo(State(state):StateArcAppState,Path(id):Pathi64,)-ResultStatusCode,AppError{letresultsqlx::query(DELETE FROM todos WHERE id ?).bind(id).execute(state.db).await?;// 删除数据影响的数据条数0时为未删除返回数据不存在ifresult.rows_affected()0{returnErr(AppError::NotFound);}Ok(StatusCode::OK)}SQLite数据库打开模式modero只读模式。moderw读写模式。moderwc读写模式数据库不存在时创建。modememory内存数据库只在程序运行期间存在。5、main.rs主文件modmethod_routers;moderror;modmodels;usecrate::method_routers::{complete_todo,create_todo,delete_todo,init_db,list_todos};useaxum::routing::{get,put};useaxum::{response::IntoResponse,Router};usetokio::net::TcpListener;#[tokio::main]asyncfnmain(){// 初始化数据库连接letshared_stateinit_db().await;// 创建路由letappRouter::new().route(/todos,get(list_todos).post(create_todo))// 查询增加.route(/todos/{id},put(complete_todo).delete(delete_todo))// 修改删除.with_state(shared_state);// 将数据库连接绑定到路由的全局状态// 绑定端口letlistenerTcpListener::bind(0.0.0.0:8080).await.unwrap();println!(添加 post请求 http://127.0.0.1:8080/todos);println!( post请求体{{\title\:\我的待办事项一\}});println!(查询所有待办事项 get请求 http://127.0.0.1:8080/todos);println!(修改 put请求 http://127.0.0.1:8080/todos/修改的id);println!(删除 delete请求 http://127.0.0.1:8080/todos/删除的id);// 启动服务axum::serve(listener,app).await.unwrap();}Path路径写法Axum 0.6及以下写法/users/:id**Axum 0.7**写法/users/{id}

更多文章