Rust Web框架Axum学习指南之响应和异常封装

发布于:2025-08-30 ⋅ 阅读:(17) ⋅ 点赞:(0)

一、添加依赖

接上一节内容,这里添加两个依赖包:serde_jsonthiserror

[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"

二、封装响应

里需要定一个响应的结构体,让结构提实现IntoResponsetrait 就可以了,处理程序可以返回任何实现了 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 常用呢)。


网站公告

今日签到

点亮在社区的每一天
去签到