Files
easygoadmin-wiki/EasyGoAdmin_Gin_AntdVue/zh/architecture/bind-mechanism.md
T
2026-10-25 17:24:27 +08:00

4.0 KiB
Raw Blame History

4.4 反射元数据驱动机制

:::tip 概述 本项目最核心的机制:RouteSpec 表即路由定义。router.Bind 反射扫描控制器方法,按声明注册路由并写入进程内路由元数据表,权限校验、操作日志、公开白名单、OpenAPI 四个消费方读同一份数据。 :::

为什么这样设计

传统做法中路由、权限注解、日志注解分散在三处,漏配一处就出安全洞。本项目把它们收敛为一条声明:

"Page": {Method: "GET", Path: "/api/dept/page", Summary: "部门分页",
         Permission: "sys:dept:page", Log: "部门管理-查询分页记录", LogType: "query"},

一条声明同时回答:路由怎么注册、谁可以访问、记不记日志、记什么类型。

Bind 执行流程

registerControllers 内 Bind(rg, new(handler.CXxx), map[string]RouteSpec{...})
        │
        ▼
反射取控制器类型的方法集(含导出方法)
        │
        ▼
按签名过滤:func (c *CXxx) M(ctx context.Context, req *dto.XxxReq) (*dto.XxxRes, error)
        │  签名不匹配 → 跳过(表现为 404,启动期即定)
        ▼
按方法名查 RouteSpec 表 → 逐条 rg.Handle(Method, Path, 包装函数)
        │
        ▼
包装函数(请求期):
  UnmarshalBody 逃生舱判断 → 绑定写入 query→body→path → binding 校验
  → 调 handler 方法 → response 信封写出
        │
        ▼
meta.Register 写入路由元数据表(进程内 map,读写锁保护)

元数据表(RouteMeta)

// internal/router/meta/meta.go
type RouteMeta struct {
    Method     string       // GET/POST/PUT/DELETE
    Path       string       // 路由模板
    Summary    string       // OpenAPI 摘要
    Permission string       // 权限节点;空=登录即可
    Log        string       // 日志标题;空=不记录
    LogType    string       // query/add/update/delete/import/export/reset
    Public     bool         // 免登录
    ReqType    reflect.Type // 请求类型(文档 schema 反射用)
    ResType    reflect.Type // 响应类型
}

存储为进程内内存表(map["GET /api/dept/page"]RouteMeta + RWMutex),启动期写入、请求期只读,无持久化与跨进程同步——生命周期与进程一致。

四个消费方(同源)

消费方 读什么 行为
authz 中间件 Permission 校验当前用户权限点集合是否命中;空则只要登录
operation_log 中间件 Log / LogType 采集请求摘要异步落库;query 类受 logQuery 开关控制
public 判断 Public IsPublicRequest 免登录放行(配合基础设施白名单)
OpenAPI 生成 全部 + ReqType/ResType /api.json 与 /swagger 端点按元数据生成文档

任一消费方都不再自己维护清单——声明改一处,四处同步生效。

绑定细节

  • 写入顺序 query → body → path,后写覆盖 → 最终优先级 path > body > query
  • 校验 读 binding 标签,错误消息取 msg 标签,失败直接信封返回
  • 逃生舱 结构体实现 UnmarshalBody(c *gin.Context) error 则跳过默认解析(文件上传)

基础设施白名单(不经元数据)

internal/middleware/public.go 维护少量不经 Bind 注册的免登录路径:

/api/health        健康检查
/api.json, /swagger*   文档端点(api.docs 开关)
/metrics           指标端点(api.metrics 开关)

业务路由的公开判断一律走元数据表,两个来源在 IsPublicRequest 汇合。

对开发的影响

场景 做法
新增接口 RouteSpec 表加一条 + handler 加同名方法,无注解、无散落注册
改权限码 只改声明,同步更新菜单节点
排查 403 看元数据表的 Permission 与角色授权
生成器 生成器自动追加 Bind 声明块——菜单/权限/路由一致性由工具保证

下一步

→ 4.5 前端分层架构