一、添加依赖
接上一节内容,这里添加两个依赖包: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
常用呢)。