4.1 整体架构概览
概述
系统采用分层架构 + 声明式基座 + 全局钩子横切 + gmeta 反射注解的组合。本节给出总架构图、模块依赖方向(允许/禁止)与启动编排,是理解全部机制的地图。
系统总架构图
text
┌───────────────────────────── 客户端 ─────────────────────────────┐
│ ui/(Vue3 + Element Plus,baseURL=/api) 其他 API 消费方 │
└──────────────────────────────────┬─────────────────────────────────┘
│ HTTP(Bearer JWT)
╔══════════════════════════════════▼═════════════════════════════════╗
║ ghttp Server(:8000) ║
║ ┌────────────────── 中间件链(顺序执行)──────────────────┐ ║
║ │ CORS → Response → RateLimit → Demo → JWT → Tenant │ ║
║ │ → OperationLog │ ║
║ └──────────────────────────┬──────────────────────────────┘ ║
║ ┌──────────────────────────▼──────────────────────────────┐ ║
║ │ Bind 反射包装层(gmeta):权限校验 → 参数解析 → 分发 │ ║
║ │ 路由元数据表 meta(权限/日志 注解即事实,补注册 goai) │ ║
║ └──────────────────────────┬──────────────────────────────┘ ║
║ controller(薄)→ service 接口(手维护)→ logic(ModuleSpec 基座) ║
║ │ 侧路:utility/{jwt,captcha,cache,upload,excel,ip2region…} ║
║ │ 侧路:gcron 调度器(job daemon + CleanTemp) ║
║ ┌────▼─────────────────────────────────────────────────────┐ ║
║ │ dao.Xxx.Ctx(ctx) —— 唯一查询入口 │ ║
║ │ hooks.ApplyCtx:del_flag=0 + 租户级表 tenant_id IN(0,x) │ ║
║ │ hooks.Handler:Insert 盖章 / Update 盖章 / Delete→软删 │ ║
║ └────┬─────────────────────────────────────────────────────┘ ║
╚══════╪══════════════════════════════════════════════════════════════╝
│ gdb(五驱动运行时切换)
┌──────▼────────┐ ┌──────────────┐ ┌─────────────────────────────┐
│ MySQL/PgSQL/… │ │ Redis(缓存) │ │ 磁盘 resource/upload + xdb │
└───────────────┘ └──────────────┘ └─────────────────────────────┘模块依赖方向图(允许 / 禁止)
text
api/v1 ◀── controller ◀── logic ──▶ service(接口注册)
│
├──▶ dao ──▶ model/entity · model/hooks ──▶ gdb
├──▶ utility/*(无业务依赖)
└──▶ consts
internal/task ──▶ internal/logic ✅ 允许(任务复用 base 能力)
internal/logic ──▶ internal/task ❌ 禁止(反向依赖)
internal/middleware ──▶ 业务包 ❌ 禁止(经 wire.go 函数变量接线)
internal/migrate ──▶ dao/logic ❌ 禁止(gdb 裸连,隔离钩子)
base.go ──▶ 模块文件 ❌ 禁止(只依赖 dao/utility/consts)启动编排(internal/cmd)
text
main.go(注册五数据库驱动 + Redis 适配器 + blank import internal/logic)
└─ internal/cmd.Run(ctx)
├─ 1) utility/cache.Init Redis 探测,失败降级进程内存
├─ 2) wireDependencies 校验中间件依赖是否已由业务包 init 接线
├─ 3) g.Server("easygoadmin") + router.Register(s)
│ 中间件链注册 + 404/500 状态处理器 + SetServerRoot("resource")
│ + /api/health + /swagger → 逐个 Bind 全部控制器
├─ 4) go DaemonInit(延时 2s) 定时任务调度器加载 status=1 任务
├─ 5) gcron 注册 CleanTemp 每日 03:30 清理上传临时目录
└─ 6) s.Run() 阻塞运行 HTTP 服务延时 2s 的原因:等 HTTP 监听就绪(任务可能是 HTTP 调自身接口)。
业务调用链(标准 CRUD)
text
Bind 包装(gmeta 权限/日志元数据)
→ controller.CXxx(薄层,仅转发 service.Xxx())
→ service.IXxx 接口(internal/service/{模块}.go,手维护)
→ logic.sXxx 实现(internal/logic/{模块}.go,ModuleSpec 基座或手写)
→ dao.Xxx.Ctx(ctx)(唯一查询入口:挂全局钩子 + 注入 del_flag/租户条件)
→ gdb → 数据库五个关键设计决策
| 决策 | 理由 |
|---|---|
| 目录平铺:api/controller/logic/service 均单包,每模块一文件 | 跨模块直接同包调用(如 user 调 ResolveCityNames 无需 import);生成器目标路径唯一 |
| service 接口手维护 | 接口即文档;禁止 gf gen service 整体覆盖 |
| logic 同包 init() 注册 | 无需 blank import,包内全量加载 |
| 中间件不依赖业务层 | IdentityLoader/TenantLoader/LogSink 以函数变量接线(wire.go),cmd 启动期检查告警 |
| dao.Ctx 唯一查询入口 | 软删/租户/审计三条红线在钩子层强制执行,业务零感知 |
分层职责速查
| 层 | 位置 | 职责 | 禁止 |
|---|---|---|---|
| api/v1 | api/v1/{模块}.go | 请求响应结构体 + gmeta 注解 | 业务逻辑 |
| controller | internal/controller/{模块}.go | 薄层透传 | 业务/dao/手写响应 |
| service | internal/service/{模块}.go | 接口契约(手维护) | 实现 |
| logic | internal/logic/{模块}.go | 业务实现(基座+钩子+手写) | 反向依赖 task |
| dao | internal/dao/ | 查询入口(钩子+红线条件) | 绕过直连 DB |
| hooks | internal/model/hooks/ | 审计盖章/软删/租户 | 业务判断 |