Rust Web框架Axum学习指南之响应和异常封装
一、添加依赖
接上一节内容,这里添加两个依赖包:serde_json
和 thiserror
[package]
name = "axum-admin"
version = "0.1.0"
edition = "2024"[dependencies]
axum = "0.8.4"
tokio = { version = "1.47.1", features = ["full"] }
serde = { version = "1.0.219", features = ["derive"] }
tracing-subscriber = "0.3.19"
# 新增的依赖
serde_json = "1.0.142"
thiserror = "2.0.14"
二、封装响应
里需要定一个响应的结构体,让结构提实现IntoResponse
的 trait
就可以了,处理程序可以返回任何实现了 IntoResponse
的东西,它将被自动转换为响应。
use axum::http::StatusCode;
use axum::Json;
use axum::response::{IntoResponse, Response};
use serde::Serialize;
use serde_json::json;const SUCCESS_CODE: i32 = StatusCode::OK.as_u16() as i32;
const SUCCESS_MESSAGE: &str = "操作成功";#[derive(Debug, Serialize)]
pub struct Message<T> {code: i32,data: Option<T>,msg: String,
}impl<T: Serialize> IntoResponse for Message<T> {fn into_response(self) -> Response {let val = json!(self);Json(val).into_response()}
}impl<T> Message<T> {pub fn success(data: T) -> Self {Self {code: SUCCESS_CODE,data: Some(data),msg: SUCCESS_MESSAGE.to_owned(),}}pub fn error(code: i32, msg: String) -> Self {Self {code,data: None,msg,}}
}
三、异常封装
这里需要使用 thiserror
,可以定一个异常枚举,存放会用的异常定义
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use thiserror::Error;
use crate::message::Message;// 类型别名
pub type MessageResult<T> = Result<Message<T>, SystemError>;#[derive(Error, Debug)]
pub enum SystemError {#[error("认证异常: {0}")]AuthError(String),#[error("服务异常:{0}")]UnknownError(String)
}impl IntoResponse for SystemError {fn into_response(self) -> Response {let (status_code, message) = match &self {SystemError::AuthError(msg) => (StatusCode::UNAUTHORIZED, msg.to_string()),SystemError::UnknownError(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg.to_string()),};(StatusCode::OK, Message::<()>::error(status_code.as_u16() as i32, message)).into_response()}
}
四、使用案例
在上一节例子中添加两个路由:
let app = Router::new().route("/", get(root)).route("/user", get(get_user)) // 获取用户.route("/user_err", get(get_user_err)) // 异常测试.route("/users", post(create_user));
控制器定义如下:
async fn get_user() -> MessageResult<User> {Ok(Message::success(User{id: 10,username: "Long".to_string()}))
}async fn get_user_err() -> MessageResult<User> {Err(SystemError::UnknownError("获取用户信息异常".to_string()))
}
最后启动项目,测试接口就可以了。
五、总结
下一篇会讲一下 axum
的提取器的使用(毕竟 CRUD
常用呢)。