API 资源
大约 1 分钟
API 资源
“API 资源”是一种约定:使用专门的 VO/Resource 结构体来组织输出,统一字段、分页与元数据,避免直接把数据库模型暴露到外部。
基础 Resource
#[derive(serde::Serialize)]
pub struct UserResource {
pub id: i64,
pub username: String,
pub real_name: Option<String>,
pub dept_name: Option<String>,
}
impl From<(entity::sys_user::Model, Option<entity::sys_dept::Model>)> for UserResource {
fn from((u, d): (entity::sys_user::Model, Option<entity::sys_dept::Model>)) -> Self {
Self {
id: u.id,
username: u.username,
real_name: u.real_name,
dept_name: d.map(|x| x.name),
}
}
}
集合 Resource 与分页
#[derive(serde::Serialize)]
pub struct Page<T> {
pub total: u64,
pub items: Vec<T>,
}
pub async fn list_users(db: &sea_orm::DatabaseConnection, page: u64, size: u64)
-> anyhow::Result<Page<UserResource>>
{
use sea_orm::{EntityTrait, QuerySelect, PaginatorTrait, LoaderTrait};
let paginator = entity::sys_user::Entity::find().paginate(db, size);
let total = paginator.num_items().await?;
let users = paginator.fetch_page(page - 1).await?;
let depts = users.load_one(entity::sys_dept::Entity, db).await?;
let items = users.into_iter().zip(depts).map(UserResource::from).collect();
Ok(Page { total, items })
}
统一响应包装
与项目的 ApiResponse<T>
搭配:
// Handler 中
let page = list_users(&db, q.page, q.size).await?;
Ok(axum::Json(ApiResponse::ok(page)))
字段控制与安全
- 通过 VO 控制返回哪些字段(隐藏密码哈希、内部标记等)
- 根据权限(claims.perms)动态决定是否包含敏感字段(如手机号/邮箱),可在组装 VO 时判断
嵌套/组合资源
- 资源中包含子资源列表:
UserResource { roles: Vec<RoleLite> }
- 注重性能:必要时使用预加载或第二次查询批量填充