299 lines
14 KiB
Markdown
299 lines
14 KiB
Markdown
# 详情查询
|
||
|
||
<cite>
|
||
**本文引用的文件**
|
||
- [routes.go](file://internal/handler/routes.go)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go)
|
||
- [profile_service.go](file://internal/service/profile_service.go)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go)
|
||
- [profile.go](file://internal/model/profile.go)
|
||
- [texture.go](file://internal/model/texture.go)
|
||
- [response.go](file://internal/model/response.go)
|
||
- [common.go](file://internal/types/common.go)
|
||
- [postgres.go](file://pkg/database/postgres.go)
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go)
|
||
</cite>
|
||
|
||
## 目录
|
||
1. [简介](#简介)
|
||
2. [项目结构](#项目结构)
|
||
3. [核心组件](#核心组件)
|
||
4. [架构总览](#架构总览)
|
||
5. [详细组件分析](#详细组件分析)
|
||
6. [依赖分析](#依赖分析)
|
||
7. [性能考量](#性能考量)
|
||
8. [故障排查指南](#故障排查指南)
|
||
9. [结论](#结论)
|
||
|
||
## 简介
|
||
本文件面向“详情查询”API,聚焦 GET /api/v1/profile/:uuid 端点。该接口为公开路由,无需认证即可访问,用于根据Minecraft用户UUID获取档案的公开信息。响应体包含档案UUID、用户名、创建时间、最后使用时间、活跃状态,以及关联的皮肤和披风信息(若存在)。该接口在Minecraft客户端通过Yggdrasil协议连接服务器时,可被用于查询玩家档案信息,以支持皮肤/披风展示等场景。
|
||
|
||
## 项目结构
|
||
围绕“详情查询”API的关键文件组织如下:
|
||
- 路由注册:在路由层定义公开的 GET /api/v1/profile/:uuid,并将其挂载到 v1 分组下。
|
||
- 处理器:实现 GetProfile 处理函数,负责参数解析、调用服务层、构造统一响应。
|
||
- 服务层:封装业务逻辑,调用仓库层进行数据查询。
|
||
- 仓库层:基于GORM执行数据库查询,预加载皮肤/披风关联。
|
||
- 模型与类型:定义档案模型、响应结构、纹理类型等。
|
||
- 数据库:PostgreSQL驱动与连接池配置。
|
||
|
||
```mermaid
|
||
graph TB
|
||
subgraph "路由层"
|
||
R["routes.go<br/>注册 /api/v1/profile/:uuid"]
|
||
end
|
||
subgraph "处理器层"
|
||
H["profile_handler.go<br/>GetProfile 处理函数"]
|
||
end
|
||
subgraph "服务层"
|
||
S["profile_service.go<br/>GetProfileByUUID"]
|
||
end
|
||
subgraph "仓库层"
|
||
REPO["profile_repository.go<br/>FindProfileByUUID"]
|
||
end
|
||
subgraph "模型与类型"
|
||
M["profile.go<br/>Profile/ProfileResponse"]
|
||
T["texture.go<br/>Texture"]
|
||
RESP["response.go<br/>统一响应结构"]
|
||
TYPES["common.go<br/>ProfileInfo"]
|
||
end
|
||
subgraph "数据库"
|
||
DB["postgres.go<br/>PostgreSQL 连接与配置"]
|
||
end
|
||
R --> H
|
||
H --> S
|
||
S --> REPO
|
||
REPO --> DB
|
||
H --> RESP
|
||
S --> M
|
||
REPO --> M
|
||
M --> T
|
||
H --> TYPES
|
||
```
|
||
|
||
图表来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [profile.go](file://internal/model/profile.go#L7-L24)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
- [common.go](file://internal/types/common.go#L154-L165)
|
||
- [postgres.go](file://pkg/database/postgres.go#L13-L74)
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
|
||
## 核心组件
|
||
- 路由层:在 v1 分组下注册 GET /api/v1/profile/:uuid,明确该端点为公开路由,无需JWT认证。
|
||
- 处理器层:GetProfile 从路径参数读取 uuid,调用服务层查询档案,构造统一响应。
|
||
- 服务层:GetProfileByUUID 调用仓库层查询档案;若未找到返回“档案不存在”错误。
|
||
- 仓库层:FindProfileByUUID 使用 uuid 条件查询,并预加载 Skin 和 Cape 关联。
|
||
- 模型与类型:Profile 定义档案字段及关联;ProfileResponse 为对外响应结构;ProfileInfo 为处理器侧返回结构;Texture 定义材质模型及其索引字段。
|
||
- 统一响应:response.go 提供统一的 Response/Error 结构,便于前后端约定。
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [profile.go](file://internal/model/profile.go#L7-L24)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
- [common.go](file://internal/types/common.go#L154-L165)
|
||
|
||
## 架构总览
|
||
下面的序列图展示了客户端调用 GET /api/v1/profile/:uuid 的典型流程,以及与Yggdrasil协议的集成场景。
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as "客户端"
|
||
participant Router as "Gin 路由"
|
||
participant Handler as "GetProfile 处理器"
|
||
participant Service as "profile_service.GetProfileByUUID"
|
||
participant Repo as "profile_repository.FindProfileByUUID"
|
||
participant DB as "PostgreSQL"
|
||
Client->>Router : "GET /api/v1/profile/ : uuid"
|
||
Router->>Handler : "路由分发"
|
||
Handler->>Service : "GetProfileByUUID(uuid)"
|
||
Service->>Repo : "FindProfileByUUID(uuid)"
|
||
Repo->>DB : "SELECT ... WHERE uuid=?<br/>并预加载 Skin/Cape"
|
||
DB-->>Repo : "Profile 记录"
|
||
Repo-->>Service : "Profile 对象"
|
||
Service-->>Handler : "Profile 对象"
|
||
Handler-->>Client : "200 + 统一响应体"
|
||
```
|
||
|
||
图表来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [postgres.go](file://pkg/database/postgres.go#L13-L74)
|
||
|
||
## 详细组件分析
|
||
|
||
### 接口定义与行为
|
||
- 路由:公开端点 GET /api/v1/profile/:uuid,无需认证。
|
||
- 请求参数:路径参数 uuid(Minecraft档案UUID)。
|
||
- 成功响应:返回统一响应结构,包含档案基本信息与关联皮肤/披风信息。
|
||
- 错误响应:当档案不存在时返回404。
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
### 响应数据结构
|
||
- 响应体字段(对外):
|
||
- uuid:档案UUID
|
||
- name:Minecraft角色名
|
||
- textures:包含皮肤与披风信息的对象
|
||
- SKIN:皮肤信息(可选)
|
||
- url:皮肤图片地址
|
||
- metadata:元数据(可选)
|
||
- model:皮肤模型(slim 或 classic)
|
||
- CAPE:披风信息(可选)
|
||
- url:披风图片地址
|
||
- metadata:元数据(可选)
|
||
- is_active:是否为活跃档案
|
||
- last_used_at:最后使用时间(可选)
|
||
- created_at:创建时间
|
||
- updated_at:更新时间
|
||
|
||
- 处理器侧返回结构(ProfileInfo):
|
||
- uuid、user_id、name、skin_id、cape_id、is_active、last_used_at、created_at、updated_at
|
||
|
||
章节来源
|
||
- [profile.go](file://internal/model/profile.go#L31-L57)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [common.go](file://internal/types/common.go#L154-L165)
|
||
|
||
### 查询流程与错误码
|
||
- 正常流程:处理器读取 uuid -> 服务层查询 -> 仓库层查询并预加载关联 -> 返回统一响应。
|
||
- 错误码:
|
||
- 404:档案不存在
|
||
- 500:服务器内部错误(数据库异常、服务层错误等)
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
Start(["进入 GetProfile"]) --> Parse["解析路径参数 uuid"]
|
||
Parse --> Query["调用服务层 GetProfileByUUID"]
|
||
Query --> RepoCall["仓库层 FindProfileByUUID(uuid)"]
|
||
RepoCall --> Found{"找到记录?"}
|
||
Found --> |是| BuildResp["组装响应含 textures"]
|
||
Found --> |否| NotFound["返回 404 档案不存在"]
|
||
BuildResp --> Ok["返回 200 + 统一响应"]
|
||
NotFound --> End(["结束"])
|
||
Ok --> End
|
||
```
|
||
|
||
图表来源
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
章节来源
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
### 与Yggdrasil协议的集成场景
|
||
- 在Minecraft客户端连接服务器时,可通过Yggdrasil的会话服务器端点获取玩家档案信息,从而展示皮肤/披风。
|
||
- 该端点与Yggdrasil的会话服务器端点存在语义上的互补:前者为公开档案详情查询,后者为认证后的会话信息查询。
|
||
- 典型调用链:客户端 -> 服务器(Yggdrasil)-> 本系统 GetProfileByUUID(公开详情查询)。
|
||
|
||
章节来源
|
||
- [yggdrasil_handler.go](file://internal/handler/yggdrasil_handler.go#L426-L440)
|
||
|
||
## 依赖分析
|
||
- 路由层依赖 Gin 路由注册,将公开端点挂载至 v1 分组。
|
||
- 处理器层依赖服务层与统一响应结构。
|
||
- 服务层依赖仓库层与数据库连接。
|
||
- 仓库层依赖 GORM 与 PostgreSQL 驱动。
|
||
- 模型层定义档案与纹理的字段、索引与关联。
|
||
|
||
```mermaid
|
||
graph LR
|
||
Routes["routes.go"] --> Handler["profile_handler.go"]
|
||
Handler --> Service["profile_service.go"]
|
||
Service --> Repo["profile_repository.go"]
|
||
Repo --> DB["postgres.go"]
|
||
Handler --> Resp["response.go"]
|
||
Service --> Model["profile.go"]
|
||
Repo --> Model
|
||
Model --> Texture["texture.go"]
|
||
Handler --> Types["common.go"]
|
||
```
|
||
|
||
图表来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [postgres.go](file://pkg/database/postgres.go#L13-L74)
|
||
- [profile.go](file://internal/model/profile.go#L7-L24)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
- [common.go](file://internal/types/common.go#L154-L165)
|
||
|
||
章节来源
|
||
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [postgres.go](file://pkg/database/postgres.go#L13-L74)
|
||
- [profile.go](file://internal/model/profile.go#L7-L24)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
- [common.go](file://internal/types/common.go#L154-L165)
|
||
|
||
## 性能考量
|
||
- 数据库索引与查询优化
|
||
- Profile 表的 uuid 字段为主键,查询命中主键索引,具备高效率。
|
||
- Profile 表的 name 字段具有唯一索引,有助于去重与唯一性约束。
|
||
- Profile 表的 user_id 字段具有普通索引,有利于按用户维度查询。
|
||
- Profile 表的 is_active 字段具有索引,便于筛选活跃档案。
|
||
- Texture 表的 hash 字段具有唯一索引,有利于快速定位材质。
|
||
- Texture 表的 uploader_id、is_public、favorite_count、download_count 等字段具有索引,便于检索与排序。
|
||
- 关联预加载
|
||
- 仓库层在查询档案时使用预加载(Preload)加载 Skin 与 Cape,减少 N+1 查询风险,提升响应速度。
|
||
- 数据库连接池
|
||
- PostgreSQL 驱动初始化时配置了连接池参数(最大空闲连接、最大打开连接、连接最大生命周期),有助于并发场景下的稳定性与吞吐量。
|
||
- 缓存建议
|
||
- 对高频查询的档案详情可引入缓存(如Redis),以进一步降低数据库压力。
|
||
- 缓存键可采用 profile:{uuid},并设置合理过期时间(如几分钟)。
|
||
- 日志与监控
|
||
- 处理器层记录错误日志,便于定位慢查询与异常。
|
||
- 建议增加指标埋点(如QPS、P95/P99延迟、错误率)以便持续优化。
|
||
|
||
章节来源
|
||
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
||
- [profile.go](file://internal/model/profile.go#L7-L24)
|
||
- [texture.go](file://internal/model/texture.go#L16-L35)
|
||
- [postgres.go](file://pkg/database/postgres.go#L13-L74)
|
||
|
||
## 故障排查指南
|
||
- 404 档案不存在
|
||
- 现象:请求返回 404,消息提示“档案不存在”。
|
||
- 排查:确认 uuid 是否正确;检查数据库中是否存在该 uuid 的档案记录。
|
||
- 500 服务器内部错误
|
||
- 现象:请求返回 500,消息提示服务层或仓库层错误。
|
||
- 排查:查看处理器层日志;检查数据库连接与连接池配置;确认 GORM 查询是否报错。
|
||
- 响应缺少皮肤/披风信息
|
||
- 现象:textures 字段为空或部分缺失。
|
||
- 排查:确认档案是否绑定了皮肤/披风;检查关联表是否存在有效记录;确认仓库层预加载是否生效。
|
||
- Yggdrasil集成问题
|
||
- 现象:客户端无法显示皮肤/披风。
|
||
- 排查:确认客户端调用的Yggdrasil端点与本系统公开详情查询端点是否一致;核对响应结构与字段命名是否匹配。
|
||
|
||
章节来源
|
||
- [profile_handler.go](file://internal/handler/profile_handler.go#L153-L195)
|
||
- [profile_service.go](file://internal/service/profile_service.go#L71-L81)
|
||
- [response.go](file://internal/model/response.go#L1-L86)
|
||
|
||
## 结论
|
||
GET /api/v1/profile/:uuid 作为公开端点,提供了基于Minecraft档案UUID的详情查询能力。其架构清晰、职责分明:路由层公开、处理器层编排、服务层封装、仓库层持久化、模型层定义。响应体包含档案基础信息与皮肤/披风信息,满足客户端在Yggdrasil协议下的集成需求。通过合理的数据库索引、关联预加载与连接池配置,可在高并发场景下保持稳定与高效。建议结合缓存与监控体系,持续优化查询性能与用户体验。 |