JQuick-Excel 导入导出闭环:从模板接收数据到结果回写
tags: #JQuickExcel #JavaExcel #开源 #POI #Excel工具
更多示例: JQuick-Excel 官网示例 https://www.jquick.org/jquick-excel/#demo-formulas0005
简介
我是 JQuick-Excel 的作者。本文将导入和导出组织成完整闭环:接收标准学生模板、转换为内部字段、完成业务处理,再输出可交付的结果表,重点处理两套映射、两份上下文和两个流的边界。
前言
真实系统通常要在一次上传后给用户返回处理结果或规范化报表。闭环的难点不在于连续调用两个 API,而在于保证输入模板、内部字段、持久化模型和输出报表之间的语义一致。本文不假设 JQuickRow 的未确认访问方法,而是把领域转换留给应用层,同时展示经测试验证的双操作 XML 契约和代理创建方式。
环境与依赖
我以 Java 8 或更高版本作为运行基线,本文固定使用 Maven 坐标io.github.paohaijiao:jquick-excel:3.6.0。仓库 POM 的项目版本为 3.6.0,并声明 Apache POI 的poi与poi-ooxml依赖,因此可读写 xls 与 xlsx 工作簿。把下面依赖写入业务工程的 pom.xml,再把 XML 服务定义放到src/main/resources/jquick-excel.xml。运行时由JQuickXmlFactory按资源名从 classpath 加载该文件;仅放在工程根目录不会参与应用资源加载。
<dependency><groupId>io.github.paohaijiao</groupId><artifactId>jquick-excel</artifactId><version>3.6.0</version></dependency><?xml version="1.0" encoding="UTF-8"?><!DOCTYPEexcelsPUBLIC"-//PAOHAIJIAO//DTD API EXCEL 1.0//EN""classpath:paohaijiao/dtd/Jquick-excel.dtd"><excelsnamespace="com.github.paohaijiao.xml.service.JQuickExcelExportService"><excelname="exportExcel"returnClass="void"><![CDATA[ EXPORT WITH SHEET="学生表", HEADER=true, MAPPING={"no":"学号","name":"姓名","sex":"性别","age":"年龄"}, TRANSFORM={"sex":trans(${dict},${sex}),"age":add(${age},1)} ]]></excel><excelname="importExcel"returnClass="java.util.List"><![CDATA[ IMPORT WITH HEADER=true, SHEET='Sheet1', MAPPING={"学号":"no","姓名":"name","性别":"sex","年龄":"age","出生日期":"birthday"}, TRANSFORM={"sex":trans(${dict},${sex}),"birthday":dateFormat(${birthday},'yyyy-MM-dd')} ]]></excel></excels>代码示例
服务接口是 XML 规则对 Java 暴露的类型化契约。namespace必须等于接口的全限定名,<excel name>必须等于方法名。测试资源使用带@Param的 field、value 参数,本文保留这个实际契约,不臆造没有在仓库中出现的代理调用形式。
packagecom.github.paohaijiao.xml.service;importcom.github.paohaijiao.statement.JQuickRow;importcom.github.paohaijiao.xml.param.Param;importjava.util.List;publicinterfaceJQuickExcelExportService{voidexportExcel(@Param("field")Stringfield,@Param("value")Stringvalue);List<JQuickRow>importExcel(@Param("field")Stringfield,@Param("value")Stringvalue);}List<JQuickRow>imported;try(InputStreamin=Pipeline.class.getClassLoader().getResourceAsStream("templates/student.xlsx")){JQuickParseHandlerparser=newJQuickExcelImportXmlParseFactory(importContext,in);JQuickFactoryfactory=newJQuickXmlFactory(parser,"jquick-excel.xml");imported=factory.createApi(JQuickExcelExportService.class).importExcel("field","value");}// 在这里完成领域校验、持久化或构造回执数据;随后将规范化数据转换为 JQuickRow。try(OutputStreamout=newFileOutputStream("students-result.xlsx")){JQuickParseHandlerparser=newJQuickExcelExportXmlParseFactory(exportContext,exportRows,out);JQuickFactoryfactory=newJQuickXmlFactory(parser,"jquick-excel.xml");factory.createApi(JQuickExcelExportService.class).exportExcel("field","value");}原理说明
闭环分为输入契约、解析转换、领域处理、结果组织和输出呈现五步。导入端以 Excel 表头为左值,输出端以内部字段为左值;二者可共享 no、name、sex、age 等字段,但不能共享同一方向的字典。由于导入与导出解析器分别绑定输入流和输出流,我分别创建代理,避免一个处理器承担相反的 I/O 职责。中间的数据库事务与错误回执属于业务层,不应由 Excel DSL 替代。
注意事项
不要直接把未经业务校验的导入结果回写给用户。应先校验必填、权限、重复键和可用字典,再决定保存、拒绝或生成带状态列的结果数据。导入流和导出流均用 try-with-resources 管理;两个 JContext 的 dict 方向应明确命名。若需大量数据,结合 JQuickExcelConfig 的流式导出、大文件导入与批次消费设置,避免一个请求占用过多内存。
总结
导入和导出连在一起时,最容易被忽视的是中间那一段领域处理。解析后的数据先完成校验、归一化和结果标记,再组织成回执报表,用户才能知道每一行究竟被接受、拒绝还是需要修正。
两套 MAPPING 和两份字典上下文应当分别维护。把它们放在同一份 XML 中并不意味着语义可以混用,明确边界才能让闭环在模板调整后仍然可追踪。