354 lines
16 KiB
Markdown
354 lines
16 KiB
Markdown
|
|
# 更新与删除
|
|||
|
|
|
|||
|
|
<cite>
|
|||
|
|
**本文档引用的文件**
|
|||
|
|
- [routes.go](file://internal/handler/routes.go)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go)
|
|||
|
|
- [auth.go](file://internal/middleware/auth.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)
|
|||
|
|
- [common.go](file://internal/types/common.go)
|
|||
|
|
- [jwt.go](file://pkg/auth/jwt.go)
|
|||
|
|
- [manager.go](file://pkg/database/manager.go)
|
|||
|
|
</cite>
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
1. [简介](#简介)
|
|||
|
|
2. [项目结构](#项目结构)
|
|||
|
|
3. [核心组件](#核心组件)
|
|||
|
|
4. [架构总览](#架构总览)
|
|||
|
|
5. [详细组件分析](#详细组件分析)
|
|||
|
|
6. [依赖关系分析](#依赖关系分析)
|
|||
|
|
7. [性能考量](#性能考量)
|
|||
|
|
8. [故障排查指南](#故障排查指南)
|
|||
|
|
9. [结论](#结论)
|
|||
|
|
|
|||
|
|
## 简介
|
|||
|
|
本章节面向需要对接“档案更新与删除”接口的开发者,重点说明以下内容:
|
|||
|
|
- PUT /api/v1/profile/:uuid 的更新流程:支持修改档案名称、更换关联的皮肤或披风材质;强调“只能修改自己名下的档案”的权限校验。
|
|||
|
|
- DELETE /api/v1/profile/:uuid 的删除流程:删除前进行权限检查与档案存在性验证。
|
|||
|
|
- 请求体格式与错误处理策略(如403无权操作、404资源不存在)。
|
|||
|
|
- 结合 service 层代码解释更新操作的事务性保证与数据一致性维护机制。
|
|||
|
|
|
|||
|
|
## 项目结构
|
|||
|
|
围绕档案更新与删除功能,涉及如下关键模块:
|
|||
|
|
- 路由层:在路由中注册了 /api/v1/profile/{uuid} 的 PUT 与 DELETE 接口,并统一使用鉴权中间件。
|
|||
|
|
- 中间件层:JWT 鉴权中间件负责解析 Authorization 头并校验令牌有效性,将用户标识注入上下文。
|
|||
|
|
- 处理器层:profile_handler 负责接收请求、绑定参数、调用 service 并输出响应。
|
|||
|
|
- 服务层:profile_service 执行业务逻辑,包含权限校验、唯一性检查、更新与删除等。
|
|||
|
|
- 仓储层:profile_repository 封装数据库访问,提供查询、更新、删除与事务性操作。
|
|||
|
|
- 模型与类型:profile 模型定义档案字段及关联关系;types 定义请求与响应结构。
|
|||
|
|
- 数据库与鉴权:GORM 管理数据库连接;JWT 用于用户身份验证。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph TB
|
|||
|
|
Client["客户端"] --> Routes["路由: /api/v1/profile/{uuid}"]
|
|||
|
|
Routes --> AuthMW["鉴权中间件: JWT"]
|
|||
|
|
AuthMW --> Handler["处理器: profile_handler"]
|
|||
|
|
Handler --> Service["服务: profile_service"]
|
|||
|
|
Service --> Repo["仓储: profile_repository"]
|
|||
|
|
Repo --> DB["数据库: GORM"]
|
|||
|
|
Handler --> Model["模型: Profile"]
|
|||
|
|
Handler --> Types["类型: UpdateProfileRequest"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
|||
|
|
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L77)
|
|||
|
|
- [profile.go](file://internal/model/profile.go#L7-L29)
|
|||
|
|
- [common.go](file://internal/types/common.go#L201-L206)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
|||
|
|
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
|||
|
|
|
|||
|
|
## 核心组件
|
|||
|
|
- 路由注册:在路由组 /api/v1/profile 下注册了 GET/:uuid、POST/、GET/、PUT/:uuid、DELETE/:uuid、POST/:uuid/activate 等接口,其中 PUT 与 DELETE 对应本节主题。
|
|||
|
|
- 鉴权中间件:要求 Authorization 头为 Bearer 令牌,校验通过后将 user_id 等信息写入上下文。
|
|||
|
|
- 处理器:UpdateProfile 与 DeleteProfile 分别调用 service 层执行业务逻辑,并根据 service 返回的错误映射为合适的 HTTP 状态码。
|
|||
|
|
- 服务层:UpdateProfile 与 DeleteProfile 在执行前均进行“档案存在性验证”和“权限校验”,并在必要时使用数据库事务保证一致性。
|
|||
|
|
- 仓储层:FindProfileByUUID、UpdateProfile、DeleteProfile 提供基础 CRUD;SetActiveProfile 使用事务确保“同一用户仅有一个活跃档案”。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L89-L109)
|
|||
|
|
|
|||
|
|
## 架构总览
|
|||
|
|
下图展示了从客户端到数据库的调用链路,以及权限校验与事务控制的关键节点。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant C as "客户端"
|
|||
|
|
participant R as "路由"
|
|||
|
|
participant M as "鉴权中间件"
|
|||
|
|
participant H as "处理器 : UpdateProfile/DeleteProfile"
|
|||
|
|
participant S as "服务 : profile_service"
|
|||
|
|
participant P as "仓储 : profile_repository"
|
|||
|
|
participant D as "数据库 : GORM"
|
|||
|
|
C->>R : "PUT /api/v1/profile/{uuid}"
|
|||
|
|
R->>M : "进入鉴权中间件"
|
|||
|
|
M-->>R : "校验通过,注入 user_id"
|
|||
|
|
R->>H : "转发请求"
|
|||
|
|
H->>S : "调用 UpdateProfile/ DeleteProfile"
|
|||
|
|
S->>P : "FindProfileByUUID"
|
|||
|
|
P->>D : "查询档案"
|
|||
|
|
D-->>P : "返回档案或记录不存在"
|
|||
|
|
P-->>S : "返回结果"
|
|||
|
|
alt "更新场景"
|
|||
|
|
S->>S : "权限校验 : profile.UserID == user_id"
|
|||
|
|
S->>P : "可选 : 名称唯一性检查"
|
|||
|
|
S->>P : "UpdateProfile(更新字段)"
|
|||
|
|
P->>D : "保存更新"
|
|||
|
|
D-->>P : "成功"
|
|||
|
|
P-->>S : "返回更新后的档案"
|
|||
|
|
else "删除场景"
|
|||
|
|
S->>S : "权限校验 : profile.UserID == user_id"
|
|||
|
|
S->>P : "DeleteProfile"
|
|||
|
|
P->>D : "删除记录"
|
|||
|
|
D-->>P : "成功"
|
|||
|
|
end
|
|||
|
|
S-->>H : "返回结果或错误"
|
|||
|
|
H-->>C : "HTTP 响应(200/403/404/500)"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L77)
|
|||
|
|
|
|||
|
|
## 详细组件分析
|
|||
|
|
|
|||
|
|
### PUT /api/v1/profile/:uuid 更新档案
|
|||
|
|
- 功能概述
|
|||
|
|
- 支持修改档案名称(可选)、更换关联的皮肤或披风材质(可选)。
|
|||
|
|
- 严格权限控制:仅允许修改“自己名下的档案”。
|
|||
|
|
- 请求路径与方法
|
|||
|
|
- 方法: PUT
|
|||
|
|
- 路径: /api/v1/profile/:uuid
|
|||
|
|
- 鉴权: 需要 Bearer 令牌
|
|||
|
|
- 请求体结构
|
|||
|
|
- 字段:
|
|||
|
|
- name: 字符串,长度范围 1-16(可选)
|
|||
|
|
- skin_id: 整数,指向材质记录的ID(可选)
|
|||
|
|
- cape_id: 整数,指向材质记录的ID(可选)
|
|||
|
|
- 示例: 仅更新名称
|
|||
|
|
- 示例: 仅更换皮肤
|
|||
|
|
- 示例: 同时更换皮肤与披风
|
|||
|
|
- 成功响应
|
|||
|
|
- 返回更新后的档案信息(包含 uuid、user_id、name、skin_id、cape_id、is_active、last_used_at、created_at、updated_at)。
|
|||
|
|
- 错误处理
|
|||
|
|
- 400: 请求参数错误(如字段校验失败)
|
|||
|
|
- 401: 未授权(缺少或无效的 Authorization 头)
|
|||
|
|
- 403: 无权操作(目标档案不属于当前用户)
|
|||
|
|
- 404: 资源不存在(档案UUID不存在)
|
|||
|
|
- 500: 服务器内部错误(数据库异常、唯一性冲突等)
|
|||
|
|
- 权限与存在性校验
|
|||
|
|
- 处理器从上下文取出 user_id,若缺失则直接返回 401。
|
|||
|
|
- 服务层先查询档案,若不存在返回 404;随后校验 profile.UserID 是否等于 user_id,否则返回 403。
|
|||
|
|
- 名称唯一性与字段更新
|
|||
|
|
- 当 name 发生变化时,服务层会检查同名是否已存在,若存在则返回 400。
|
|||
|
|
- skin_id 与 cape_id 为可选字段,仅当传入非空值时才更新对应字段。
|
|||
|
|
- 事务性与一致性
|
|||
|
|
- 更新操作本身通过单条 save/update 完成,不涉及跨表事务。
|
|||
|
|
- 若未来扩展为多步更新(例如同时更新多个关联字段),建议在服务层使用 GORM 事务包裹,确保原子性与一致性。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
Start(["进入 UpdateProfile"]) --> Parse["解析请求体<br/>name/skin_id/cape_id"]
|
|||
|
|
Parse --> GetCtx["从上下文获取 user_id"]
|
|||
|
|
GetCtx --> HasUser{"user_id 存在?"}
|
|||
|
|
HasUser --> |否| Resp401["返回 401 未授权"]
|
|||
|
|
HasUser --> |是| Load["查询档案 FindProfileByUUID"]
|
|||
|
|
Load --> Found{"档案存在?"}
|
|||
|
|
Found --> |否| Resp404["返回 404 资源不存在"]
|
|||
|
|
Found --> |是| Perm{"档案归属校验<br/>profile.UserID == user_id"}
|
|||
|
|
Perm --> |否| Resp403["返回 403 无权操作"]
|
|||
|
|
Perm --> |是| NameChk{"是否更新 name?"}
|
|||
|
|
NameChk --> |是| Dup{"检查同名是否存在"}
|
|||
|
|
Dup --> |是| Resp400["返回 400 参数错误"]
|
|||
|
|
Dup --> |否| Apply["应用字段更新<br/>name/skin_id/cape_id"]
|
|||
|
|
NameChk --> |否| Apply
|
|||
|
|
Apply --> Save["保存更新 UpdateProfile"]
|
|||
|
|
Save --> Reload["重新加载档案 FindProfileByUUID"]
|
|||
|
|
Reload --> Resp200["返回 200 成功"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L280)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L135)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L71)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L280)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L135)
|
|||
|
|
- [common.go](file://internal/types/common.go#L201-L206)
|
|||
|
|
|
|||
|
|
### DELETE /api/v1/profile/:uuid 删除档案
|
|||
|
|
- 功能概述
|
|||
|
|
- 删除指定 UUID 的档案。
|
|||
|
|
- 删除前进行权限检查与档案存在性验证。
|
|||
|
|
- 请求路径与方法
|
|||
|
|
- 方法: DELETE
|
|||
|
|
- 路径: /api/v1/profile/:uuid
|
|||
|
|
- 鉴权: 需要 Bearer 令牌
|
|||
|
|
- 成功响应
|
|||
|
|
- 返回成功消息(message: "删除成功")。
|
|||
|
|
- 错误处理
|
|||
|
|
- 401: 未授权(缺少或无效的 Authorization 头)
|
|||
|
|
- 403: 无权操作(目标档案不属于当前用户)
|
|||
|
|
- 404: 资源不存在(档案UUID不存在)
|
|||
|
|
- 500: 服务器内部错误(数据库异常)
|
|||
|
|
- 删除流程
|
|||
|
|
- 处理器从上下文取出 user_id,若缺失则直接返回 401。
|
|||
|
|
- 服务层先查询档案,若不存在返回 404;随后校验权限,不匹配返回 403。
|
|||
|
|
- 通过权限校验后执行删除,成功返回 200。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant C as "客户端"
|
|||
|
|
participant H as "处理器 : DeleteProfile"
|
|||
|
|
participant S as "服务 : profile_service"
|
|||
|
|
participant P as "仓储 : profile_repository"
|
|||
|
|
participant D as "数据库 : GORM"
|
|||
|
|
C->>H : "DELETE /api/v1/profile/{uuid}"
|
|||
|
|
H->>S : "调用 DeleteProfile(uuid, user_id)"
|
|||
|
|
S->>P : "FindProfileByUUID"
|
|||
|
|
P->>D : "查询"
|
|||
|
|
D-->>P : "返回档案或不存在"
|
|||
|
|
P-->>S : "结果"
|
|||
|
|
alt "档案不存在"
|
|||
|
|
S-->>H : "返回 404"
|
|||
|
|
H-->>C : "404"
|
|||
|
|
else "权限校验失败"
|
|||
|
|
S-->>H : "返回 403"
|
|||
|
|
H-->>C : "403"
|
|||
|
|
else "权限通过"
|
|||
|
|
S->>P : "DeleteProfile"
|
|||
|
|
P->>D : "删除记录"
|
|||
|
|
D-->>P : "成功"
|
|||
|
|
S-->>H : "返回 nil"
|
|||
|
|
H-->>C : "200 成功"
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L282-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L137-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L73-L77)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L282-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L137-L159)
|
|||
|
|
|
|||
|
|
### 权限验证与鉴权中间件
|
|||
|
|
- 中间件职责
|
|||
|
|
- 校验 Authorization 头格式(Bearer token)。
|
|||
|
|
- 使用 JWT 服务验证令牌有效性,并将 user_id、username、role 写入上下文。
|
|||
|
|
- 处理器侧使用
|
|||
|
|
- 处理器从上下文读取 user_id,若不存在则返回 401。
|
|||
|
|
- 服务层进一步校验档案归属,不匹配返回 403。
|
|||
|
|
- JWT 服务
|
|||
|
|
- 生成与验证使用 HS256 签名算法,过期时间可配置。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
|||
|
|
- [jwt.go](file://pkg/auth/jwt.go#L10-L71)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
|
|||
|
|
### 事务性保证与数据一致性
|
|||
|
|
- 更新操作
|
|||
|
|
- 当前 UpdateProfile 通过单次 save/update 完成,不涉及跨表事务。
|
|||
|
|
- 若未来扩展为多步更新(例如同时更新多个字段或关联表),建议在服务层使用 GORM 事务包裹,确保原子性与一致性。
|
|||
|
|
- 删除操作
|
|||
|
|
- DeleteProfile 为单条删除,不涉及跨表事务。
|
|||
|
|
- 活跃档案设置
|
|||
|
|
- SetActiveProfile 使用 GORM 事务,先将用户所有档案设为非活跃,再将目标档案设为活跃,保证“同一用户仅有一个活跃档案”的约束。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L135)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L137-L188)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L89-L109)
|
|||
|
|
|
|||
|
|
## 依赖关系分析
|
|||
|
|
- 路由依赖
|
|||
|
|
- profile 路由组使用鉴权中间件,确保后续接口均需有效 JWT。
|
|||
|
|
- 处理器依赖
|
|||
|
|
- profile_handler 依赖鉴权中间件提供的 user_id,依赖 service 层执行业务逻辑,依赖 model/types 定义的数据结构。
|
|||
|
|
- 服务层依赖
|
|||
|
|
- profile_service 依赖 repository 层进行数据访问,依赖数据库连接管理器。
|
|||
|
|
- 仓储层依赖
|
|||
|
|
- profile_repository 依赖 GORM 与数据库连接。
|
|||
|
|
- 鉴权与数据库
|
|||
|
|
- jwt.go 提供令牌签发与校验;manager.go 提供数据库连接获取与迁移。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
graph LR
|
|||
|
|
Routes["routes.go"] --> AuthMW["auth.go"]
|
|||
|
|
AuthMW --> Handler["profile_handler.go"]
|
|||
|
|
Handler --> Service["profile_service.go"]
|
|||
|
|
Service --> Repo["profile_repository.go"]
|
|||
|
|
Repo --> DBMgr["manager.go"]
|
|||
|
|
Handler --> Types["common.go"]
|
|||
|
|
Handler --> Model["profile.go"]
|
|||
|
|
Handler --> JWT["jwt.go"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
图表来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
|||
|
|
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L77)
|
|||
|
|
- [manager.go](file://pkg/database/manager.go#L35-L50)
|
|||
|
|
- [common.go](file://internal/types/common.go#L201-L206)
|
|||
|
|
- [profile.go](file://internal/model/profile.go#L7-L29)
|
|||
|
|
- [jwt.go](file://pkg/auth/jwt.go#L10-L71)
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [routes.go](file://internal/handler/routes.go#L63-L79)
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L77)
|
|||
|
|
- [manager.go](file://pkg/database/manager.go#L35-L50)
|
|||
|
|
|
|||
|
|
## 性能考量
|
|||
|
|
- 查询与预加载
|
|||
|
|
- 仓储层在查询档案时使用预加载关联的皮肤与披风,有助于减少 N+1 查询问题,提升响应速度。
|
|||
|
|
- 事务范围
|
|||
|
|
- 当前更新与删除均为单条操作,事务开销较小;若扩展为多步更新,建议将相关操作合并到事务中,避免部分成功导致的不一致。
|
|||
|
|
- 唯一性检查
|
|||
|
|
- 更新名称时进行同名检查,避免并发场景下的重复;建议在数据库层面增加唯一索引以降低竞争条件风险。
|
|||
|
|
- 日志与可观测性
|
|||
|
|
- 处理器在发生错误时记录日志,便于定位问题;建议在服务层也增加关键步骤的日志埋点。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [profile_repository.go](file://internal/repository/profile_repository.go#L19-L31)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L135)
|
|||
|
|
|
|||
|
|
## 故障排查指南
|
|||
|
|
- 401 未授权
|
|||
|
|
- 检查请求头 Authorization 是否为 Bearer 令牌格式;确认令牌未过期且签名正确。
|
|||
|
|
- 403 无权操作
|
|||
|
|
- 确认当前用户是否拥有目标档案;检查档案所属 user_id 与当前用户是否一致。
|
|||
|
|
- 404 资源不存在
|
|||
|
|
- 确认档案 UUID 是否正确;检查数据库中是否存在该记录。
|
|||
|
|
- 400 参数错误
|
|||
|
|
- 检查请求体字段是否符合长度与类型要求;例如 name 长度应在 1-16 之间。
|
|||
|
|
- 500 服务器错误
|
|||
|
|
- 查看服务端日志,关注数据库连接、唯一性冲突、事务回滚等问题。
|
|||
|
|
|
|||
|
|
章节来源
|
|||
|
|
- [profile_handler.go](file://internal/handler/profile_handler.go#L197-L339)
|
|||
|
|
- [profile_service.go](file://internal/service/profile_service.go#L92-L159)
|
|||
|
|
|
|||
|
|
## 结论
|
|||
|
|
- PUT /api/v1/profile/:uuid 与 DELETE /api/v1/profile/:uuid 已具备完善的权限校验与存在性验证机制。
|
|||
|
|
- 更新操作支持名称与材质字段的灵活更新,删除操作简洁可靠。
|
|||
|
|
- 服务层与仓储层清晰分离职责,当前更新与删除为单步操作;若未来扩展为多步更新,建议引入事务以保障一致性。
|
|||
|
|
- 建议在数据库层面完善唯一性约束,并在服务层增加关键步骤的日志埋点,以便于问题定位与性能优化。
|