罗展丰
Published on 2026-06-17 / 58 Visits
0
0

打印模块架构设计

一、整体架构

打印模块分两层:框架层(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()
  • 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)

Comment