JasperReports:棘手的部分
如果您使用Java进行编程的时间足够长,则有可能需要为业务用户生成报告。 就我而言,我已经看到几个项目使用JasperReports®库来生成PDF和其他文件格式的报告。 最近,我荣幸地观察了Mike和他的团队使用上述报告库及其面临的挑战。
简而言之JasperReports
简而言之,使用JasperReports(JR)生成报告涉及三个步骤:
- 加载已编译的报告(即,加载
JasperReport
对象) - 通过用数据填充报告来运行报告(结果是
JasperPrint
对象) - 将填充的报告导出到文件(例如,使用
JRPdfExporter
导出到PDF)
在Java代码中,看起来像这样。
JasperReport compiledReport = JasperCompileManager.compileReport("sample.jrxml");
Map<String, Object> parameters = ...;
java.sql.Connection connection = dataSource.getConnection();
try {JasperPrint filledReport = JasperFillManager.fillReport(compiledReport, parameters, connection);JasperExportManager.exportReportToPdf(filledReport, "report.pdf");
} finally {connection.close();
}
多亏了facade类,这看起来很简单。 但是外表可能是骗人的!
鉴于以上代码段(以及概述的三个步骤),您认为哪些部分需要最多的时间和内存? (听起来像面试问题)。
如果您回答(#2)填写数据,那是对的! 如果您回答了#3,那也是正确的,因为#3与#2成正比。
恕我直言 ,大多数在线教程仅显示简单的部分。 就JR而言 ,似乎缺少对较困难和棘手的部分的讨论。 在这里,与Mike的团队一起,我们遇到了两个困难:内存不足错误和长期运行的报告。 使这些困难特别令人难忘的是,它们仅在生产过程中出现(而不在开发过程中)。 我希望通过共享它们,将来可以避免它们。
内存不足错误
第一个挑战是报告内存不足。 在开发过程中,与实际操作数据相比,我们用于运行报告的测试数据将太小。 因此, 为此设计 。
在我们的例子中,所有报告都使用JRVirtualizer
运行。 这样,当达到内存中的页面/对象最大数量时,它将刷新到磁盘/文件。
在此过程中,我们还了解到虚拟器需要清理。 否则,周围会有几个临时文件。 而且,只有在报告导出到文件后 ,我们才能清理这些临时文件。
Map<String, Object> parameters = ...;
JRVirtualizer virtualizer = new JRFileVirtualizer(100);
try {parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);...... filledReport = JasperFillManager.fillReport(compiledReport, parameters, ...);// cannot cleanup virtualizer at this pointJasperExportManager.exportReportToPdf(filledReport, ...);
} finally {virtualizer.cleanup();
}
有关更多信息,请参见Virtualizer Sample – JasperReports 。
请注意,当我们在运行报表时遇到内存不足的错误时,JR 并不总是罪魁祸首。 有时,即使在使用JR之前,我们也会遇到内存不足错误。 我们看到了如何滥用JPA来加载报告的整个数据集( Query.getResultList()
和TypedQuery.getResultList()
)。 同样,由于数据集仍然很小,因此在开发期间不会显示该错误。 但是,当数据集太大而无法容纳在内存中时,我们会遇到内存不足错误。 我们选择避免使用JPA生成报告。 我猜我们只需要等待JPA 2.2的Query.getResultStream()
可用即可。 我希望JPA的Query.getResultList()
返回Iterable
。 这样,就有可能一次映射一个实体,而不是整个结果集。
现在,避免加载整个数据集。 一次加载一个记录。 在此过程中,我们返回了良好的JDBC。 不错,JR很好地使用了ResultSet
。
长期运行的报告
第二个挑战是长期运行报告。 同样,在开发过程中可能不会发生这种情况。 充其量,将运行10秒钟左右的报告视为冗长。 但是,有了实际的运行数据,它可以运行大约5-10分钟。 当根据HTTP请求生成报告时,这尤其麻烦。 如果报告可以在超时时间段内(通常为60秒或最多5分钟)开始写入响应输出流,那么它很有可能被请求用户(通常是通过浏览器)接收。 但是,如果填写报告需要5分钟以上的时间,而导出到文件又需要8分钟,那么用户将只会看到超时的HTTP请求,并将其记录为错误。 听起来有点熟?
请记住,报告可能会运行几分钟。 因此, 为此设计 。
就我们而言,我们在单独的线程上启动报告。 对于通过HTTP请求触发的报告,我们将以一个页面进行响应,该页面包含指向所生成报告的链接。 这样可以避免超时问题。 当用户单击此链接而报告尚未完成时,他/她将看到仍在生成报告。 但完成的报告时,他/她就可以看到生成的报告文件。
ExecutorService executorService = ...;
... = executorService.submit(() -> {Map<String, Object> parameters = ...;try {...... filledReport = JasperFillManager.fillReport(compiledReport, parameters, ...);JasperExportManager.exportReportToPdf(filledReport, ...);} finally {...}
});
我们还必须添加停止/取消运行报告的功能。 好东西,JR有检查Thread.interrupted()
代码。 因此,仅中断线程将使其停止。 当然,您需要编写一些测试来进行验证(期望JRFillInterruptedException
和ExportInterruptedException
)。
在讨论过程中,我们重新发现了将“监听器”添加到报告生成中的方法(例如FillListener
和JRExportProgressMonitor
)并为用户提供一些进度信息。
我们还创建了实用程序测试类,以通过反复重复给定的数据来生成大量数据。 这对于帮助团队的其他成员开发专为处理长期运行和内存不足错误而设计的JR应用程序很有用。
进一步的设计考虑
要考虑的另一件事是填写报告时需要打开和关闭所需的资源。 这可以是JDBC连接,Hibernate会话,JPA EntityManager
或文件输入流(例如CSV,XML)。 下图是我的设计注意事项的粗略草图。
1. Compiling- - - - - - - - - - - - - -\- - - -\ \
2. Filling > open-close \- - - -/ resource > swap to file/
3. Exporting /- - - - - - - - - - - - - -/
我们要隔离#2并定义装饰器,这些装饰器将打开资源,填充报告并在finally
块中关闭打开的资源。 打开的资源可能取决于报表中的<queryString>
元素(如果存在)。 在某些情况下,如果没有<queryString>
元素,则可能无需打开资源。
<queryString language="hql"><![CDATA[ ... ]]>
</queryString>
...
<queryString language="csv"><![CDATA[ ... ]]>
</queryString>
此外,我们还希望将#2和#3组合为一种抽象。 这种单一的抽象使您可以更轻松地进行增强装饰,例如将创建的页面对象刷新为文件,并在导出过程中将其加载回。 如前所述,这就是JRVirtualizer
所做的。 但是我们希望使用结合#2和#3的抽象对对象透明的设计。
致谢
目前为止就这样了。 再次感谢Mike和他的团队分享了他们的经验。 是的,他是将自己应用的收入捐赠给慈善机构的那个人 。 另外,还要感谢克莱尔(Claire)通过一次又一次重复给定数据进行测试的想法。 相关代码段可以在GitHub上找到 。
翻译自: https://www.javacodegeeks.com/2018/01/jasperreports-tricky-parts.html
JasperReports:棘手的部分相关推荐
- jasperreports_JasperReports:棘手的部分
jasperreports 如果您使用Java进行编程的时间足够长,则有可能需要为业务用户生成报告. 就我而言,我已经看到几个项目使用JasperReports®Library来生成PDF和其他文件格 ...
- MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决
MySQL 系列(一) 生产标准线上环境安装配置案例及棘手问题解决 一.简介 MySQL是最流行的开放源码SQL数据库管理系统,它是由MySQL AB公司开发.发布并支持的.有以下特点: MySQL是 ...
- 虚拟化管理的两大棘手之处
虚拟化技术是柄双刃剑:一方面企业可以据此实现敏捷生产.精益运营和高效灾备,另一方面虚拟化管理方法论.工具集和可参考最佳实践的缺失,会让企业深陷糟糕虚拟化管理的泥沼不能自拔. 以Vertex制药为例.从 ...
- 报表工具JasperReports视频教程
JasperReports是一个基于Java的开源报表工具,它可以在Java环境下像其它IDE报表工具一样来制作报表.JasperReports 支持PDF.HTML.XLS.CSV和XML文件输出格 ...
- BZOJ 2333 【SCOI2011】 棘手的操作
题目链接:棘手的操作 网上的题解大部分都是在线用可并堆艹--但是树高严格\(\log\)的可并堆我不会啊--还是离线大法好-- 我们可以先把所有的合并操作用并查集给处理好,把得到的森林记录下来.然后, ...
- JasperReports是一个开源的java报表制作引擎
JasperReports是一个开源的java报表制作引擎 http://jasperreports.sourceforge.net iReport是JasperReports的一个GUI工具,用来生 ...
- jasperreports java web报表_iReport+jasperReports制作WEB报表
JasperReports介绍 JasperReports是一个强大的,灵活的报表生成工具,能够生成 PDF,WORD,EXCEL,HTML,XML格式的报表.JasperReports的开发是由一份 ...
- influxdb无法实现关联表_双汇:从棘手的InfluxDB+Redis到TDengine
双汇发展多个分厂的能源管控大数据系统主要采用两种技术栈:InfluxDB/Redis和Kafka/Redis/HBase/Flink,对于中小型研发团队来讲,无论是系统搭建,还是实施运维都非常棘手.经 ...
- 对待棘手bug,新手与大牛的差距在哪里?
阿里妹导语:一行代码引发周边童鞋的Xcode内存爆炸.作为一名喜欢探究到底的工程师,岂能袖手旁观?来自高德的涛澜童鞋,给出了一个样本式的解决思路.下面就让我们一起走进"案发现场". ...
最新文章
- 信号状态关_路由器要不要关?难怪信号越来越差
- 一个torch版本报错
- VS2022+.NET6 RC1+C#10,.NET开发起飞
- 如何在苹果官网下载旧版本的Xcode 方法
- Java中使用BigDecimal进行浮点数精确计算 超大整数 浮点数等计算 没有数位限制
- YII实现dropDownList 联动事件
- Java存储任意对象_浅析java设计模式(一)----异构容器,可以存储任何对象类型为其他类提供该对象...
- 外参矩阵转四元数,左右手坐标系转化1
- Base64编码流程
- UDS协议之诊断会话管理服务 0x10
- 金士顿DT100 G3 PS2251-07海力士U盘量产修复成功教程
- 快速学会linux上的chrony服务
- 2021年全球印度香米收入大约12530百万美元,预计2028年达到21670百万美元
- 苹果慌了,iPhone11全系大降价抢市场
- spring boot 使用 bboss 操作 ES
- scarpy-爬取链家所有成交数据
- ***.jar!\BOOT-INF\classes!\***.xml没有此文件
- Python基础:字符集和编码
- 可擦写光盘不能擦除和刻写_光盘怎么判断是否可擦写
- 能帮你找到网页设计灵感的16个网站-沪江UI团队资料翻译组
热门文章
- 编译原理(四)之解析语言翻译成三地址代码
- 两年摸爬滚打 Spring Boot,总结了这 16 条最佳实践
- 一次恐怖的 Java 内存泄漏排查实战
- Java多线程系列--“JUC线程池”06之 Callable和Future
- 阿里巴巴对Java编程【注释规约】的规约
- Node.JS第二讲笔记
- 使用java将字符串写入到指定的文件中
- css实现一级下拉菜单
- JQuery 表单校验
- 第3步 (请先看第2步再看第3步) 新建完spring+springmvc+mybatis项目 需要推送gitee仓库进行管理 巨详细