一、整体架构
打印模块分两层:框架层(framework-print)和业务层(sys-biz/print)。
┌─────────────────────────────────────────────────────────────┐
│ sys-biz / print (业务层) │
│ PrintConfiguration ──→ PrintInitialization (复用框架逻辑) │
│ PrintTemplateInfoService (模板CRUD / OSS上传 / 设计器) │
│ PrintBartenderService (BarTender打印代理) │
│ print_proxy_gui.exe (本地Python代理) │
└────────────────────────────┬────────────────────────────────┘
│ 依赖
┌────────────────────────────▼────────────────────────────────┐
│ framework-print (框架层,独立JAR) │
│ PrintAutoConfiguration ──→ PrintMetadataInitialization │
│ FrameworkPrintService (元数据注册 + 数据获取) │
│ FrameworkPrintController (/v1/print/get-data) │
│ @PrintPlan / @PrintScheme / @PrintSchemeColumn (注解) │
│ AbstractBillPrintable / AbstractSpecifyData (抽象基类) │
│ MetadataPlan / MetadataScheme / MetadataProperty (元数据) │
└─────────────────────────────────────────────────────────────┘
- framework-print — 通用打印框架,提供注解扫描、元数据解析、数据获取的完整能力,独立于任何业务系统
- sys-biz/print — 业务层接管初始化流程(
PrintConfiguration),复用框架的注解/元数据体系,并增加模板管理、OSS存储、BarTender打印等业务功能
二、模块位置
| 模块 | 路径 |
|---|---|
| 框架层 | E:\workplace\imom-common\imom-framework\framework-print |
| 业务层 | E:\workplace\imom-sys\sys-biz\src\main\java\com\sie\imom\sys\print |
三、框架层(framework-print)
3.1 目录结构
framework-print/src/main/java/com/sie/mbm/mom/framework/print/
├── annotation/
│ ├── PrintPlan.java # 打印方案声明(类级)
│ ├── PrintScheme.java # 数据源声明(类级)
│ └── PrintSchemeColumn.java # 列元数据声明(字段级)
├── config/
│ ├── PrintAutoConfiguration.java # 自动配置入口
│ └── PrintConfigProperties.java # 配置属性 (mom.print.*)
├── constants/
│ └── PrintConstants.java # 常量定义
├── controller/
│ └── FrameworkPrintController.java # 通用打印数据接口
├── core/
│ ├── FrameworkPrintService.java # 数据获取服务(TABLE/CUSTOM分发)
│ ├── PrintMetadataInitialization.java # 注解扫描 + 元数据解析
│ └── metadata/
│ ├── MetadataPlan.java # 方案元数据
│ ├── MetadataScheme.java # 数据源元数据
│ └── MetadataProperty.java # 列元数据
├── dto/
│ ├── PrintDataDTO.java # 打印请求DTO
│ └── PrintPreviewDataDTO.java # 预览数据DTO
├── enums/
│ ├── PrintPlanCategory.java # 方案类别 (TABLE / CUSTOM)
│ ├── PreviewDataStrategy.java # 预览策略 (FIRST / SPECIFY)
│ └── PrintExceptionEnum.java # 异常枚举
├── util/
│ ├── PrintUtils.java # 工具类
│ └── PrintTransformUtils.java # 元数据转DTO工具
├── AbstractBillPrintable.java # CUSTOM模式抽象基类
└── AbstractSpecifyData.java # SPECIFY预览策略抽象基类
3.2 自动装配流程
Spring Boot 启动
└→ spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
└→ PrintAutoConfiguration (条件: mom.print.enable=true)
├→ 注册 FrameworkPrintService Bean
├→ 注册 PrintMetadataInitialization Bean
├→ @ComponentScan 扫描 FrameworkPrintController
└→ @EventListener(ApplicationReadyEvent) → init()
└→ PrintMetadataInitialization.init()
├→ 扫描所有 @PrintPlan 注解的 Bean
├→ 逐个 parsePlan(Class)
│ ├→ 判断类型: AbstractBillPrintable子类 → CUSTOM
│ │ BaseEntity/BasicEntity子类 → TABLE
│ ├→ 提取 @PrintPlan.code / name
│ ├→ parseClass() 递归解析 @PrintScheme / @PrintSchemeColumn
│ │ ├→ 简单类型 → 构建 MetadataProperty
│ │ ├→ 集合类型 → 递归解析泛型
│ │ └→ 引用类型 → 递归解析类
│ └→ 注册到 FrameworkPrintService.dataMap
└→ savePrintPlan()
└→ 转换为 PrintSchemeCreateDTO → 通过 Feign 批量保存
3.3 核心类职责
| 类 | 职责 |
|---|---|
PrintAutoConfiguration |
自动配置入口,装配 Bean,触发初始化 |
PrintMetadataInitialization |
注解扫描 + 元数据解析 + 方案持久化 |
FrameworkPrintService |
元数据注册/查询 + 打印数据获取(TABLE/CUSTOM路由) |
FrameworkPrintController |
通用 REST API 提供打印数据获取 |
MetadataPlan |
一个打印方案的完整元数据(含多个 MetadataScheme) |
MetadataScheme |
一个数据源的完整元数据(含多个 MetadataProperty) |
MetadataProperty |
一个数据列的元数据(code/name/type) |
3.4 数据获取路由
FrameworkPrintService.getPrintData(printCode, ids) 根据 PrintPlanCategory 分派:
- TABLE 模式: 反射调用实体对应的 Mapper.
selectListByIds(ids),自动查询数据库 - CUSTOM 模式: 从 Spring 容器获取 Bean,调用
AbstractBillPrintable.printData(ids)
FrameworkPrintService.getPreviewData(printCode) 分派:
- FIRST 策略:
- TABLE → Mapper.
paginate(1, 1, QueryWrapper)取第一条 - CUSTOM →
AbstractBillPrintable.previewData()
- TABLE → Mapper.
- SPECIFY 策略: 实例化
AbstractSpecifyData子类,调用其previewData()
3.5 框架层通用 API
POST /v1/print/get-data
{
"planCode": "taskPrint",
"ids": ["799665818685509"] // 可选,不传则走预览
}
由框架直接提供,无需业务层开发额外的数据获取接口。
四、业务层(sys-biz/print)
4.1 目录结构
print/
├── bartender/
│ ├── controller/ # BarTender打印代理接口
│ ├── demoprintable/ # 示例: TaskPrintable / DictPrintable
│ ├── dto/ # 打印请求DTO
│ ├── py/ # Python本地代理 (print_proxy_gui.py)
│ └── service/ # PrintBartenderService / BarTenderService
│
└── template/
├── config/
│ ├── PrintConfiguration.java # 业务启动入口(替代框架自动配置)
│ └── PrintInitialization.java # 复用框架逻辑 + 本地持久化
├── controller/ # 模板分类/方案/模板 CRUD API
├── convert/ # MapStruct DTO转换
├── dto/ # 业务DTO
├── entity/ # PrintTemplateInfo / PrintScheme / PrintTemplateCategory
├── enums/ # PrintErrorCodeEnum / PrintTemplateTypeEnum 等
├── mapper/ # MyBatis-Flex Mapper
└── service/ # PrintTemplateInfoService / PrintSchemeService 等
4.2 启动流程:PrintConfiguration 接管初始化
PrintConfiguration 是业务层的启动入口,目的在于复用框架注解解析逻辑,但方案数据保存到本地的 sys_print_scheme 表,而非通过 Feign 远程调用。
PrintConfiguration (@Configuration, mom.print.enable=true)
├→ 注册 FrameworkPrintService Bean (bizFrameworkPrintService)
├→ 注册 PrintInitialization Bean
└→ @EventListener(ApplicationReadyEvent) → init()
└→ PrintInitialization.init() (业务版)
├→ 扫描 @PrintPlan 注解
├→ 复用框架的注解解析逻辑(parsePlan / parseClass)
│ ├→ 类型判断: CUSTOM / TABLE (与框架一致)
│ ├→ 元数据解析: @PrintScheme + @PrintSchemeColumn
│ ├→ 递归解析嵌套类型 (与框架一致)
│ └→ 额外校验: code/name 重复检测
├→ 注册到本地 FrameworkPrintService
└→ savePrintPlan()
└→ 转为本地 PrintSchemeCreateDTO → printSchemeService.batchSave()
└→ 直接写入本地 sys_print_scheme 表(非 Feign)
框架版 vs 业务版的区别:
| 对比项 | framework-print (框架) | sys-biz/print (业务) |
|---|---|---|
| 配置入口 | PrintAutoConfiguration (AutoConfiguration.imports) |
PrintConfiguration (@Configuration) |
| 初始化类 | PrintMetadataInitialization |
PrintInitialization (复用解析逻辑) |
| Bean 名 | frameworkPrintService (无别名) |
bizFrameworkPrintService (显式限定) |
| 方案保存 | 通过 FrameworkRemotePrintSchemeService (Feign) |
通过 PrintSchemeService (本地MyBatis) |
| 额外校验 | 无 | code/name 重复检测 |
4.3 模板管理
业务层核心:围绕三张业务表实现模板的完整生命周期管理。
sys_print_template_category (模板分类)
├→ 树形结构 (pid 自关联)
├→ 支持 name/code 关键字搜索
└→ CRUD + 启用/停用 + 树形查询
sys_print_scheme (打印方案)
├→ 启动时由 PrintInitialization 自动同步
├→ 存储 metadataJson (JSON格式数据源元数据)
└→ CRUD + 启用/停用
sys_print_template_info (打印模板)
├→ 关联 scheme (schemeId / schemeCode / schemeName)
├→ 关联 category (categoryId,支持子分类自动包含)
├→ 关联 OSS 文件 (fileId)
├→ 区分报表类型 (reportName: sieReport / bartender)
├→ 区分模板类型 (templateType: label / document)
├→ 状态管理 (启用/禁用/作废) + 复制
└→ 文件操作:
├→ 单文件上传 (.sied JSON数组,逐条解析创建)
├→ 批量上传 (.btw / .sied,解析文件名反查方案)
├→ 多模板下载 (合并为 .sied JSON)
├→ 设计器打开 (有 fileId→读OSS, 无→构建默认结构)
└→ 设计器保存 (删除旧文件→上传新文件→更新fileId)
4.4 BarTender 打印代理
PrintBartenderService
├→ printProxy() — 接收打印请求
│ ├→ getPrintable(schemeCode) — 根据方案编码找 @PrintPlan Bean
│ ├→ printBean.printData(ids) — 获取业务数据
│ └→ barTenderService.printProxy() — 调用本地Python代理
│
└→ download() — 调试下载
├→ printBean.previewData() — 获取预览数据
├→ getCsvContent() — 转为 CSV (| 分隔符)
├→ getBtwContent() — 获取 .btw 模板
└→ packZip() — 打包 data.csv + xxx.btw → ZIP下载
4.5 与框架层的交互
业务代码完全依赖框架层的注解体系:
// 业务层开发的 Printable
@PrintPlan(code = "taskPrint", name = "任务打印") // ← 框架注解
@PrintScheme(name = "任务打印信息") // ← 框架注解
public class TaskPrintable extends AbstractBillPrintable { // ← 框架基类
@Override
public Map<String, List<?>> printData(List<String> ids) { ... }
@Override
public Map<String, List<?>> previewData() { ... }
}
框架层提供注解和基类,业务层实现具体逻辑。运行时框架层的 FrameworkPrintService 通过 SpringContextHolder.getBean() 获取业务 Bean 并调用方法。
五、配置项
| 配置 | 类型 | 默认值 | 说明 |
|---|---|---|---|
mom.print.enable |
Boolean | true |
是否启用打印模块,设为 false 则跳过所有打印初始化 |
mom.print.async |
Boolean | true |
是否异步初始化方案。异步可避免阻塞应用启动,推荐生产环境开启 |
mom.print.stop-start |
Boolean | false |
解析 @PrintPlan 失败时是否中止应用启动。生产环境不建议开启 |
mom.print.auto-destroy |
Boolean | true |
元数据初始化完成后是否自动销毁打印上下文释放内存 |
默认情况无需任何配置,以上均为默认值。如需禁用打印模块:
mom:
print:
enable: false
六、错误码
| 错误码 | 说明 |
|---|---|
PRINT_CODE_NOT_EXIST |
打印方案编码不存在 |
| 1900001 ~ 1900009 | 业务层错误(PrintErrorCodeEnum) |