news 2026/4/17 22:52:49

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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; charset=utf-8(status,msg).into_response()}}// 实现从 sqlx::Error 自动转到 AppError (可以使用 “?” 操作符)// 可以实现其他错误类型的转换,做到错误处理统一implFrom<sqlx::Error>forAppError{fnfrom(err:sqlx::Error)->Self{AppError::DatabaseError(err)}}
  • StatusCode:Axum 提供的 HTTP 状态码枚举,如StatusCode::NOT_FOUNDStatusCode::INTERNAL_SERVER_ERROR,用于标准化响应状态。
  • IntoResponse:Axum 的核心 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()->Arc<AppState>{// 创建数据库连接,读写模式,数据库不存在时创建letpool=SqlitePool::connect("sqlite:todo.db?mode=rwc").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):State<Arc<AppState>>,Json(payload):Json<CreateTodo>,)->Result<(StatusCode,Json<Todo>),AppError>{letid=sqlx::query("INSERT INTO todos (title,completed) VALUES (?,0)").bind(&payload.title).execute(&state.db).await?.last_insert_rowid();// 返回创建记录的idletnew_todo=Todo{id,title:payload.title,completed:false,};Ok((StatusCode::CREATED,Json(new_todo)))}// 查询所有待办事项pubasyncfnlist_todos(State(state):State<Arc<AppState>>,)->Result<(StatusCode,Json<Vec<Todo>>),AppError>{lettodos=sqlx::query_as("SELECT id,title,completed FROM todos").fetch_all(&state.db)// 查询全部数据.await?;Ok((StatusCode::OK,Json(todos)))}// 完成一项待办事项pubasyncfncomplete_todo(State(state):State<Arc<AppState>>,Path(id):Path<i64>,)->Result<StatusCode,AppError>{letresult=sqlx::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):State<Arc<AppState>>,Path(id):Path<i64>,)->Result<StatusCode,AppError>{letresult=sqlx::query("DELETE FROM todos WHERE id = ?").bind(id).execute(&state.db).await?;// 删除数据影响的数据条数,0时为未删除,返回数据不存在ifresult.rows_affected()==0{returnErr(AppError::NotFound);}Ok(StatusCode::OK)}

SQLite数据库打开模式:

  • mode=ro:只读模式。

  • mode=rw:读写模式。

  • mode=rwc:读写模式,数据库不存在时创建。

  • mode=memory:内存数据库,只在程序运行期间存在。

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_state=init_db().await;// 创建路由letapp=Router::new().route("/todos",get(list_todos).post(create_todo))// 查询,增加.route("/todos/{id}",put(complete_todo).delete(delete_todo))// 修改,删除.with_state(shared_state);// 将数据库连接,绑定到路由的全局状态// 绑定端口letlistener=TcpListener::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}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 22:50:54

从ORA-01882看Java时区那些坑:JVM、Docker和Oracle的“三角恋”

从ORA-01882看Java时区那些坑&#xff1a;JVM、Docker和Oracle的“三角恋” 在分布式系统架构中&#xff0c;时区问题就像一颗定时炸弹&#xff0c;随时可能在最意想不到的时刻引爆。当Java应用通过JDBC连接Oracle数据库时&#xff0c;ORA-01882错误就像一个顽固的幽灵&#xf…

作者头像 李华
网站建设 2026/4/17 22:48:28

JSTL 标签库详解与实战案例

目录 一、JSTL 基础认知 1. 什么是 JSTL&#xff1f; 2. JSTL 的 5 大标签库 二、JSTL 下载与使用 1. 依赖包下载 2. 基于Maven项目 3. 使用 三、JSTL 核心标签库实战 前置准备&#xff1a;JavaBean 实体类 1. MyUser.java&#xff08;用户实体&#xff09; 2. Prod…

作者头像 李华
网站建设 2026/4/17 22:43:09

day3-实训学习记录

重定向标准输入重定向<<并不表示追加&#xff0c;而是表示输入结束的意思&#xff0c;即作为一个结束符这条命令在查找文件的同时&#xff0c;把正确的结果既保存到文件中&#xff0c;又统计了行数&#xff0c;同时把错误提示显示在屏幕上管道 | 只传递标准输出&#xff…

作者头像 李华
网站建设 2026/4/17 22:42:05

CFturbo 2024保姆级教程:从流量扬程到三维叶轮,手把手搞定离心泵水力设计

CFturbo 2024离心泵水力设计全流程实战指南 离心泵作为工业领域最常用的流体输送设备之一&#xff0c;其水力设计质量直接影响着泵的效率、寿命和运行稳定性。传统的手工设计方法不仅耗时费力&#xff0c;而且难以快速验证设计方案的合理性。CFturbo作为专业的流体机械设计软件…

作者头像 李华