背景
数据模型/数据源原本是"只读 + 启动时写死":DataModel 由 example 启动扫描 classpath 生成、写死 id="default" 注册为 Bean;DB/API/EXCEL/JSON 四个提取器实现不存在;连接测试、表/列探查、凭证加密、DataSource 持久化能力全无。
本 issue 跟踪把"建一次、多报表复用"的数据模型变成可 CRUD 独立资产、并接入真实数据源的完整工作。
模块边界
example → starter → report-engine-datasource(新) → report-engine-framework → report-engine-excel
datasource 模块只提供能力(提取器/凭证/converter),REST API 全归 starter(架构约定:"全部通用 REST API 在 starter")。领域抽象留 framework,实现进 datasource(依赖倒置,不反向依赖)。
整体计划(三期)
- 一期:后端基础设施(数据源管理后端 + 渲染链路多模型多源 + starter service 分层)
- 二期:前端管理界面 + 剩余提取器(API/EXCEL/JSON)+ 前端契约同步
- 三期:治理(版本/引用追踪/关系画布/下推优化/凭证 KMS)
✅ 已完成(一期 + 分层重构)
分支:datasource-mgmt-backend(commit c3c1c51)
新模块 report-engine-datasource
CredentialService:AES/GCM 凭证加解密 + 脱敏(JDK javax.crypto,密钥 report.datasource.crypto.key,缺省告警)
DataModelConfigConverter:domain ↔ DTO 双向转换,加解密在转换处
DbDataExtractor:JDBC 提取 + test + listTables/listColumns(含主键/外键标记)
DataModelMgmtAutoConfiguration:注册能力 Bean(提取器/凭证/converter)
framework 抽象层(零 Spring)
DataModelRepository 接口 + DataModelConfig 实体 + DataModelDtos DTO record(DataSourceDTO/DatasetDTO/UnionMemberDTO/RelationshipDTO/FieldDTO)
DataExtractor 加 default 方法(test/listTables/listColumns)+ TestResult/ColumnMeta
starter service 分层
- 新建
service 包:DataModelService / DataSourceService / ReportConfigService / ReportRenderService
- 5 个 Controller 改薄(业务下沉 service,含从 datasource 迁回的
DataModelMgmtController/DataSourceController)
- 渲染链路:从单例
DataModel 改为按 dataModelId 从仓库加载 + List<DataExtractor> 派发
RenderRequest 加 dataModelId;删除旧 DataModelController
example
InMemoryDataModelRepository + RepositoryConfig 注册
DatasetConfig 重构为 DataModelSeeder(@EventListener(ApplicationReadyEvent) 写仓库,删 @Bean DataModel/CsvDataExtractor)
验证
- 全量
install -DskipTests 通过
- framework + datasource 单测全过(CredentialService / DbDataExtractor(H2) / DataModelConfigConverter)
- example 启动:seeder 写入 11 数据集 + 2 关系,10 示例报表兼容
- curl 端到端:
GET /api/datamodels、GET /api/datamodels/default(脱敏)、POST /api/datasources/test(H2 ok:true)、GET /api/datasets?dataModelId=default、POST /api/report/preview(渲染出 workbook)全通
🚧 未完成(二期)
前端管理界面
前端契约同步(破坏性,随二期一起)
剩余提取器
🔜 未完成(三期:治理)
关键设计决策
| 决策点 |
选择 |
理由 |
| 模块依赖方向 |
datasource → framework |
依赖倒置:抽象留 framework,实现进 datasource |
| 连接持久化 |
内嵌 DataModelConfig |
一模型一份连接,贴合现有 DataModel.datasources,渲染自包含 |
| Dataset 序列化 |
DTO record 承接 |
sealed 无 Jackson 注解,照 ConfigDtos 范式,不加 @JsonTypeInfo |
| 凭证 |
AES/GCM + enc: 前缀 + *** 脱敏 |
三态:持久加密 → 运行解密 → 出口脱敏;*** 回填旧值 |
| 提取器扩展 |
supports() + 注册表 + default 方法 |
新增类型零改动接入,未实现能力显式抛异常 |
| CSV 提取器位置 |
留 framework |
轻量、无重依赖、作测试夹具;DB/API/EXCEL/JSON 进 datasource |
| Controller 归属 |
全在 starter |
架构约定,datasource 只提供能力 |
背景
数据模型/数据源原本是"只读 + 启动时写死":
DataModel由 example 启动扫描 classpath 生成、写死id="default"注册为 Bean;DB/API/EXCEL/JSON四个提取器实现不存在;连接测试、表/列探查、凭证加密、DataSource 持久化能力全无。本 issue 跟踪把"建一次、多报表复用"的数据模型变成可 CRUD 独立资产、并接入真实数据源的完整工作。
模块边界
datasource 模块只提供能力(提取器/凭证/converter),REST API 全归 starter(架构约定:"全部通用 REST API 在 starter")。领域抽象留 framework,实现进 datasource(依赖倒置,不反向依赖)。
整体计划(三期)
✅ 已完成(一期 + 分层重构)
分支:
datasource-mgmt-backend(commitc3c1c51)新模块 report-engine-datasource
CredentialService:AES/GCM 凭证加解密 + 脱敏(JDKjavax.crypto,密钥report.datasource.crypto.key,缺省告警)DataModelConfigConverter:domain ↔ DTO 双向转换,加解密在转换处DbDataExtractor:JDBC 提取 +test+listTables/listColumns(含主键/外键标记)DataModelMgmtAutoConfiguration:注册能力 Bean(提取器/凭证/converter)framework 抽象层(零 Spring)
DataModelRepository接口 +DataModelConfig实体 +DataModelDtosDTO record(DataSourceDTO/DatasetDTO/UnionMemberDTO/RelationshipDTO/FieldDTO)DataExtractor加 default 方法(test/listTables/listColumns)+TestResult/ColumnMetastarter service 分层
service包:DataModelService/DataSourceService/ReportConfigService/ReportRenderServiceDataModelMgmtController/DataSourceController)DataModel改为按dataModelId从仓库加载 +List<DataExtractor>派发RenderRequest加dataModelId;删除旧DataModelControllerexample
InMemoryDataModelRepository+RepositoryConfig注册DatasetConfig重构为DataModelSeeder(@EventListener(ApplicationReadyEvent)写仓库,删@Bean DataModel/CsvDataExtractor)验证
install -DskipTests通过GET /api/datamodels、GET /api/datamodels/default(脱敏)、POST /api/datasources/test(H2ok:true)、GET /api/datasets?dataModelId=default、POST /api/report/preview(渲染出 workbook)全通🚧 未完成(二期)
前端管理界面
report-datasource(连接配置表单 + 表/列探查树 + 数据集管理 + 关系列表编辑)/datamodels路由(列表页 + 模型设计器三栏)app-pc依赖 + 菜单入口report-api补数据源管理 API 客户端(listDataModelsCRUD /testConnection/exploreTables/exploreColumns)前端契约同步(破坏性,随二期一起)
RenderRequest预览/导出/反查请求补传dataModelIdGET /api/datasets加dataModelId参数(/engine页面当前不可用,二期重做时适配)剩余提取器
API(HTTP → JSON)EXCELJSON🔜 未完成(三期:治理)
DRAFT/PUBLISHED已有字段,流程未做)AUTO外键自动扫描建关系(DbDataExtractor.listColumns已返回外键元数据,可作数据源)report.datasource.management.enabled)CLAUDE.md模块结构图 + starter/service 分层描述关键设计决策
DataModelConfigDataModel.datasources,渲染自包含ConfigDtos范式,不加@JsonTypeInfoenc:前缀 +***脱敏***回填旧值supports()+ 注册表 + default 方法