整体架构
Ako 把“页面怎么渲染”和“数据怎么保存”拆开。前端只认识协议,后端适配器把协议映射到自己的模型、数据库和 Web 框架。
四层关系
text
┌──────────────────────────────────────────────────────────┐
│ Vue 3 前端 @ako-dev/ako │
│ 菜单 / 搜索 / 表格 / 编辑 / 按钮 / 自定义组件 │
└───────────────────────┬──────────────────────────────────┘
│ JSON over HTTP
┌───────────────────────▼──────────────────────────────────┐
│ Ako 协议 │
│ auth · menu · model/page · model/save · model/delete │
└───────────────────────┬──────────────────────────────────┘
│
┌───────────────────────▼──────────────────────────────────┐
│ 后端框架适配器 │
│ 路由、鉴权、序列化、事务、错误处理、请求参数绑定 │
└───────────────────────┬──────────────────────────────────┘
│
┌───────────────────────▼──────────────────────────────────┐
│ 业务与数据访问 │
│ Model / Repository / ORM / SQL / 外部服务 │
└──────────────────────────────────────────────────────────┘当前 JVM 实现还可以细分为:
| 层 | 当前源码 | 作用 |
|---|---|---|
| 协议核心 | ako-core | 定义 DbModel、DbField、按钮、查询请求和分页响应。 |
| JPA 基础 | ako-jpa | 提供 JPA 模型基类、软删除模型和查询辅助。 |
| Rain 适配 | ako-rain | 在 Rain + SmartWeb + SmartAccess 环境中发现模型、注册控制器并执行查询。 |
| Spring 适配 | ako-spring-common、ako-springboot-2/3/4、ako-springboot-springdata | 由 Spring Boot 自动配置建立 Runtime;Boot 3/4 可直接使用 Spring Data JPA,Boot 2 可接入公共 SPI。 |
一次页面请求发生什么
启动阶段
前端 Ako 插件安装默认页面节点和内置字段类型。AkoBootView 调用 auth/isAuth,认证成功后进入主界面。
菜单阶段
主界面调用 menu/list/{channel}。响应中的 models 是后端当前可用的模型元数据,前端把它们转成菜单项和 EntityView。menus 用于补充分组或自定义页面。
查询阶段
EntityView 维护搜索条件、排序条件和分页状态,调用:
text
POST model/page/{model}
{
"page": 1,
"size": 20,
"params": { "name_like": "%Alice%" },
"sort": { "id": "desc" }
}后端返回当前页实体,以及字段类型所需的 information。例如 ako:mapping 会在这里携带关联模型的展示数据。
编辑阶段
edit 不为 null 的字段会生成表单项;editable: false 会生成不可编辑输入。提交时前端把表单对象 POST 到 model/save/{model},后端必须重新做权限、类型和业务校验。
扩展阶段
元数据中的节点名称最终会交给 ako.findComponent(name);类型名称最终会交给 ako.findTypeProvider(type)。因此扩展的关键是:
- 后端输出稳定的字符串标识。
- 前端在 Vue App 中注册同名组件或 TypeProvider。
- 两端对
options的 JSON 结构达成约定。
协议优先带来的好处
- 后端可以从 Rain 迁移到 Spring 或其他框架,而无需重写管理后台。
- 前端可以替换默认 UI,而不改变业务接口。
- 协议可以单独做契约测试,不必把测试绑定到某一个 ORM。
- 复杂业务可以保留手写页面,标准模型页面继续使用自动生成。
设计时要守住的边界
- 元数据是输入,不是权限系统。
permission、Scene等字段不能替代后端授权判断。 FunctionValidate、FetchValidate和按钮eval运行在浏览器中,不能承载机密或最终业务规则。- 查询操作符来自客户端,适配器应该白名单校验字段、操作符和排序方向。
- 只要后端使用不同的主键类型,删除接口仍应接受字符串化 ID,避免 UUID 或大整数在前端丢失精度。