# javaService Print **Repository Path**: tejiaju/java-service-print ## Basic Information - **Project Name**: javaService Print - **Description**: 一个简单的Java本地打印服务,根据docx模板打印。 很适合B/S项目打印小票、简单报表等。 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2025-12-13 - **Last Updated**: 2025-12-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 打印服务项目介绍 ## 概述 本项目是一个基于 Spring Boot 的文档模板打印服务,支持 `.doc/.docx` 模板参数替换、通过 WebSocket 接收打印任务、异步队列处理、集成系统打印机输出(如 `Microsoft Print to PDF`)。适用于发票、订单、出库单等单据的自动化生成与打印。 ## 核心特性 - 模板处理:Apache POI(HWPF 处理 `.doc`,XWPF 处理 `.docx`) - 占位符替换:支持 `${param}` 形式;严格模式缺参报错 - 动态表格行:在 `.docx` 模板中按参数自动复制“模板行”填充 `items.N.*` - 异步队列:线程池并发处理打印任务,实时推送状态 - WebSocket 接口:JSON 指令下发、ACK/STATUS/DONE/ERROR 反馈 - 打印集成:系统打印机(默认或指定) - 可配置:模板根路径、默认打印机、并发度、严格模式等 - 日志与异常:SLF4J + Logback,完善的异常捕获与反馈 ## 架构与模块 - Controller(WebSocket):`PrintWebSocketHandler` 解析 JSON、入队 - Service(业务):`TemplateService` 模板填充,`PrinterService` 打印,`PrintQueueService` 队列与状态推送 - Repository(资源):`TemplateRepository` 安全加载模板文件 - Config(配置):`WebSocketConfig`、`PrintConfig`、`TemplateProperties`、`PrintProperties` ## 目录结构 ``` print-service/ src/main/java/com/example/print/ PrintApplication.java bootstrap/ TemplateBootstrap.java config/ WebSocketConfig.java PrintConfig.java TemplateProperties.java PrintProperties.java controller/ PrintWebSocketHandler.java repository/ TemplateRepository.java service/ TemplateService.java PrinterService.java PrintQueueService.java processor/ DocumentProcessor.java HwpfProcessor.java XwpfProcessor.java model/ PrintRequest.java PrintOptions.java PrintJob.java PrintJobStatus.java util/ PlaceholderUtils.java src/main/resources/ application.yml logback-spring.xml templates/ invoice.docx (示例) ``` ## 文件说明 - `PrintApplication.java`:应用入口,启用异步与配置绑定 - `bootstrap/TemplateBootstrap.java`:运行时生成示例模板(可选) - `config/WebSocketConfig.java`:注册 `/ws/print` WebSocket 端点 - `config/PrintConfig.java`:注册文档处理器与线程池,配置并发队列 - `config/TemplateProperties.java`:模板根路径配置属性 - `config/PrintProperties.java`:默认打印机、队列并发等打印属性 - `controller/PrintWebSocketHandler.java`:接收 JSON 指令、参数校验、入队、推送状态 - `repository/TemplateRepository.java`:按根路径安全加载模板文件,防路径穿越 - `service/TemplateService.java`:按扩展名选择处理器,执行占位符替换并输出临时文件 - `service/PrinterService.java`:解析系统打印机,构造 `DocPrintJob` 并提交打印 - `service/PrintQueueService.java`:异步任务队列,推进状态 `FILLING_TEMPLATE/PRINTING/DONE/ERROR` - `service/processor/DocumentProcessor.java`:文档处理器接口,定义 `supports/process` - `service/processor/HwpfProcessor.java`:`.doc` 模板文本占位符替换 - `service/processor/XwpfProcessor.java`:`.docx` 模板处理,支持动态表格“模板行”复制与填充 - `model/PrintRequest.java`:WebSocket 请求 DTO(模板路径、参数、打印配置、选项) - `model/PrintOptions.java`:打印选项 DTO(份数、单双面、作业名、打印机) - `model/PrintJob.java`:队列任务实体(任务 ID、状态、选项等) - `model/PrintJobStatus.java`:任务状态枚举 - `util/PlaceholderUtils.java`:占位符解析与替换(严格/非严格) - `src/main/resources/application.yml`:应用配置示例(模板根路径、默认打印机、并发度) - `src/main/resources/logback-spring.xml`:日志输出级别与格式配置 - `templates/invoice.docx`:示例模板(含动态行“模板行”与基础占位符) ## 运行与构建 - JDK 17+ - 使用 Maven Wrapper 构建:`./mvnw.cmd -DskipTests package` - 启动应用:`java -jar target/print-service-*.jar` - 访问 WebSocket:`ws://localhost:8080/ws/print` > 如果企业环境存在 SSL 证书限制导致 Maven Wrapper 下载失败,可使用本地 Maven 或配置企业镜像。 ## 配置说明 - `application.yml` 示例: ```yaml template: rootPath: templates print: defaultPrinter: Microsoft Print to PDF queueMaxConcurrency: 4 ``` - `TemplateProperties`:模板根路径(相对或绝对),防止路径穿越 - `PrintProperties`:默认打印机名、队列并发度等 ## 模板设计与占位符 - 普通文本占位符:`${customerName}`、`${order.id}`、`${amount}`、`${date}` - Word 中尽量保证占位符不被样式拆分为多个 Run,避免替换失败 - `.doc`:支持普通占位符替换,不支持动态行复制 - `.docx`:支持表格“模板行”动态复制(见下) ## 动态表格行(.docx) - 在表格中保留一行作为“数据模板行”,该行的每个单元格使用不带索引的占位符: - `${items.name}`、`${items.qty}`、`${items.total}` - 传参使用 `items.N.field`(N 为 0、1、2…): ```json { "templatePath": "invoice.docx", "params": { "customerName": "张三", "order.id": "A123", "amount": "257.00", "date": "2025-12-13", "items.0.name": "鼠标", "items.0.qty": "1", "items.0.total": "99.00", "items.1.name": "键盘", "items.1.qty": "1", "items.1.total": "158.00" }, "print": { "copies": 1, "duplex": false, "jobName": "Invoice-A123", "printerName": "Microsoft Print to PDF" }, "options": { "strict": true } } ``` - 服务会自动计算 `items` 数量并复制模板行 N 次,逐行填充 - 严格模式下,模板行中使用到的字段缺失会报错 ## WebSocket 协议 - 连接:`ws://localhost:8080/ws/print` - 客户端请求(`PrintRequest`): - `templatePath`:模板相对路径(基于 `template.rootPath`) - `params`:键值对占位符参数 - `print`:打印配置(`copies`、`duplex`、`jobName`、`printerName`) - `options.strict`:是否严格校验缺参 - 服务端消息: - `ACK`:收到任务,包含 `jobId` - `STATUS`:处理中状态,如 `FILLING_TEMPLATE`、`PRINTING` - `DONE`:完成 - `ERROR`:出错,包含 `message` ## 打印机配置 - 指定打印机:`print.printerName` 或在配置中设置 `defaultPrinter` - 使用系统可用打印机名称(如 Windows 的 `Microsoft Print to PDF`) ## 日志与异常处理 - 日志:`logback-spring.xml` 控制输出级别与格式 - 异常:模板加载、防路径穿越、占位符缺参、POI 处理、打印过程异常都会被捕获并通过 `ERROR` 消息返回 ## 安全与路径防护 - 模板加载时会将目标路径规范化并校验必须位于模板根目录内,防止路径穿越 ## 扩展性 - 处理器接口 `DocumentProcessor` 支持新增格式实现(如未来支持 `.pdf`、`.xlsx`) - 队列并发可通过配置动态调整 ## 常见问题与排查 - `XmlValueDisconnectedException`:在 `.docx` 动态行处理中已修复为先缓存模板行文本再删除行 - 占位符被拆分:确保 `${...}` 在 Word 中为连续文本,不要跨 Run - 打印样式:当前复制行为按文本填充,不复制单元格样式;建议在表格/列设置通用样式,必要时可扩展深拷贝单元格属性 - Maven 下载失败:企业环境证书或网络限制,使用本地 Maven 或企业镜像 ## 示例模板 - 路径:`templates/invoice.docx` - 表头行:`名称 | 数量 | 金额` - 数据模板行:`${items.name} | ${items.qty} | ${items.total}` - 其他文本:`客户名:${customerName}`、`订单编号:${order.id}`、`金额:${amount}`、`日期:${date}` ## 许可证 本项目示例代码供学习与集成参考,未附带特定许可证,按企业内部规范使用。