转换为PDF后如何获取Jasper Report中已填充的参数值
结论
该需求完全可以实现,针对不同使用场景有两种可落地的方案:
方案一:直接从JasperPrint对象获取参数(单元测试首选)
你现有代码中完成报表填充后生成的JasperPrint对象本身就存储了所有填充时传入的参数,不需要解析PDF字节数组,也不需要修改现有业务逻辑,是单元测试场景下最简便的实现方式。
操作代码
// 你原有代码中的JasperPrint对象 JasperPrint jasperPrint = JasperFillManager .fillReport(resourceFile.getInputStream(), parameters, new JREmptyDataSource()); // 直接调用方法获取所有填充用参数 Map<String, Object> filledParams = jasperPrint.getParameters(); // 单元测试断言示例(以JUnit 5为例) String actualFullName = (String) filledParams.get("name"); org.junit.jupiter.api.Assertions.assertEquals("张三 李四", actualFullName);
方案二:从PDF字节数组中提取参数(仅适用于只能拿到PDF文件的场景)
如果你的单元测试只能拿到最终生成的PDF字节数组,无法获取JasperPrint对象,可以在导出PDF时把需要校验的参数写入PDF自定义元数据,后续再从PDF中读取元数据即可。
步骤1:修改PDF导出逻辑,写入自定义元数据
改用JRPdfExporter导出PDF,同时把需要校验的参数写入PDF的XMP自定义元数据:
import net.sf.jasperreports.engine.export.JRPdfExporter; import net.sf.jasperreports.export.SimpleExporterInput; import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; import net.sf.jasperreports.export.SimplePdfExporterConfiguration; // 原有填充逻辑不变 Map<String, Object> parameters = new HashMap<>(); parameters.put("name", (employee.getFirstName() + " " + employee.getLastName())); JasperPrint jasperPrint = JasperFillManager .fillReport(resourceFile.getInputStream(), parameters, new JREmptyDataSource()); // 导出时写入自定义元数据 JRPdfExporter exporter = new JRPdfExporter(); exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream)); SimplePdfExporterConfiguration config = new SimplePdfExporterConfiguration(); // 写入自定义参数到元数据,前缀可自定义,避免和系统元数据冲突 config.addXmpMetadataProperty("custom:fullName", (String) parameters.get("name")); exporter.setConfiguration(config); exporter.exportReport(); byte[] content = outputStream.toByteArray();
步骤2:单元测试读取PDF元数据
引入PDFBox依赖,读取PDF中的自定义元数据做校验:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentInformation; // 读取PDF字节数组中的元数据 try (PDDocument pdfDoc = PDDocument.load(content)) { PDDocumentInformation docInfo = pdfDoc.getDocumentInformation(); String actualFullName = docInfo.getCustomMetadataValue("custom:fullName"); // 执行断言 org.junit.jupiter.api.Assertions.assertEquals("张三 李四", actualFullName); }
方案对比
- 方案一无需修改业务逻辑、无需引入额外依赖,执行效率高,是单元测试场景的首选
- 方案二仅适用于无法获取
JasperPrint对象,只能拿到最终PDF的特殊场景
内容的提问来源于stack exchange,提问作者Hamza Belmellouki
相关产品推荐
相关产品推荐

