JasperReports:棘手的部分

如果您使用Java进行编程的时间足够长,则有可能需要为业务用户生成报告。 就我而言,我已经看到几个项目使用JasperReports®库来生成PDF和其他文件格式的报告。 最近,我荣幸地观察了Mike和他的团队使用上述报告库及其面临的挑战。

简而言之JasperReports

简而言之,使用JasperReports(JR)生成报告涉及三个步骤:

  1. 加载已编译的报告(即,加载JasperReport对象)
  2. 通过用数据填充报告来运行报告(结果是JasperPrint对象)
  3. 将填充的报告导出到文件(例如,使用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()代码。 因此,仅中断线程将使其停止。 当然,您需要编写一些测试来进行验证(期望JRFillInterruptedExceptionExportInterruptedException )。

在讨论过程中,我们重新发现了将“监听器”添加到报告生成中的方法(例如FillListenerJRExportProgressMonitor )并为用户提供一些进度信息。

我们还创建了实用程序测试类,以通过反复重复给定的数据来生成大量数据。 这对于帮助团队的其他成员开发专为处理长期运行和内存不足错误而设计的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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348088.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

win mysql 2003错误_windows MySql 报1067错误 2003错误

1067错误原因是我把安装mysql的目录的名字改了。但是位于目录里面的my.ini配置文件没有修改&#xff0c;玛德我真傻逼。把my.ini的#Path to installation directory. All paths are usually resolved relative to this.basedir"D:/My_MySQL/"这下面一行的路径名改成目…

java heroku_Heroku和Java –从新手到初学者,第1部分

java heroku最近&#xff0c;我听说Heroku允许在Cedar堆栈中部署Java应用程序。 由于没有真正的软件构想&#xff0c;我决定尝试一下&#xff0c;仅配置SOMETHING以在Heroku上运行。 我对ReST有所了解&#xff08;我仍然想学习并练习&#xff09;&#xff0c;所以我决定我的第…

mysql 合服_风云私服合区的方法详解(mysql数据库合并)

只能合并帐号&#xff0c;MY的库不能合并。倒数据前请留好备份&#xff0c;防止发生以外&#xff0c;破坏你得数据&#xff0c;切忌.1)首先确认你的机器上必须装MySQL 以及 mysql-connector-odbc-5.1.1-win32.msimysql-connector-odbc-5.1.1-win32.msi 就是 MySQL ODBC 5.1,你可…

mysql自定义数据类型_MySQL中的数据类型

一.MySQL中的数值类型分类MySQL中数值类型主要有三类&#xff1a;数字类型&#xff0c;字符串类型&#xff0c;时间类型。1.数字类型1.1整数tinyint 1字节smallint 2字节mediumint 3字节int 4字节bigint …

分布式系统开发注意点_分布式系统开发注意事项

分布式系统开发注意点开发分布式软件系统时&#xff0c;要考虑许多因素。 如果您甚至不知道第一句话中我在说什么&#xff0c;那么让我为您提供一些见解&#xff0c;示例以及有关分布式系统的实例。 总览 分布式系统是指多个物理硬件设备与单独的离散用户交互并通过这些硬件设…

String#repeat来到Java吗?

JDK-8197594 &#xff08;“ String&#xff03;repeat”&#xff09;在其“描述”中包括以下内容&#xff1a;“长期以来&#xff0c;一直要求一种用于重复字符序列的String方法&#xff0c;没有后续操作。” 可以在JDK-8197594的“问题链接”中找到有关String类中用于重复字符…

mysql 什么是幻读_何为幻读?MySQL又是如何解决幻读的?

一、什么是幻读在一次事务里面&#xff0c;多次查询之后&#xff0c;查询的结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行二、为什么要解决幻读在高并发数据库系统中&#xff0c;需要保证事务与事务之间的隔离性&#xff0c;还有事务本身的一致性。三、…

电子电气架构——车载ECU刷写工具vFlash简介

电子电气架构——车载ECU刷写工具vFlash简介 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 没有人关注你。也无需有人关注你。你必须承认自己的价值&a…

mysql执行系统命令_mysql 命令行执行 sql

1.直接输入sql执行MySQL> select now();---------------------| now() |---------------------| 2013-09-18 13:55:45 |---------------------1 row in set (0.00 sec)2.执行编写好的sql脚本mysql> source /home/1.sql---------------------| now() |-------------------…

jboss7.1.1 部署_在JBoss AS 7上部署BroadleafCommerce 2.0

jboss7.1.1 部署前2个步骤实际上与Broadleaf无关&#xff0c;但是提到该步骤是为了使其易于执行&#xff08;复制/粘贴&#xff09;这些步骤。 步骤&#xff03;1&#xff1a;在JBoss AS中配置数据源。 <datasource jta"true" jndi-name"java:jboss/datasou…

java中n次方怎么表示_java如何计算一个数的n次方

java递归算法&#xff0c;代码如下&#xff1a;public class Test3 { public double zhishu(double x,double y){ if(y>0){ return x*zhishu(x,y-1); }else if(y<0){ return (x*zhishu(x,-y-1)); }else{ return 1; } } public double fuzhishu(…

枚举集合的EnumSet

在上一篇博客文章中&#xff0c;我们发现了EnumMap用于带有枚举键的映射。 您可能已经观察到&#xff0c;还有一个专门针对枚举优化的Set &#xff1a; EnumSet 。 我们再次定义一个CoffeeType枚举&#xff1a; public enum CoffeeType {ESPRESSO, POUR_OVER, FRENCH_PRESS, …

linux下mkdir头文件_Linux中判断一个目录是否存在,如果不存在就创建这个目录

在操作文件目录时我们常常会考虑如下的功能&#xff1a;1、判断文件是否存在&#xff0c;并判断文件是否可写/目录是否存在Linux下&#xff1a;#includeint access(const char* pathname, int mode);参数介绍&#xff1a;返回值&#xff1a;成功0&#xff0c;失败-1pathname 是…

mac 连接hbase的图形化界面_MAC安装Hbase以及Hbase基本命令

安装Hbase1&#xff0e;官网下载安装包&#xff0c;我下载的是hbase-2.4.0-bin.tar.gz。2&#xff0e;解压&#xff1a;tar zxf hbase-2.4.0-bin.tar.gz3&#xff0e;安装JDK&#xff0c;并设置JAVA_HOME&#xff0c;通过vi ~/.bash_profile&#xff0c;设置环境变量export JAV…

ldap java_使用LDAP保护Java EE6中的Web应用程序

ldap java在上一篇文章中&#xff0c;我们解释了如何在通过传输层安全性&#xff08;TLS&#xff09;/安全套接字层&#xff08;SSL&#xff09;传输数据时保护数据。 现在让我们尝试了解如何为使用LDAP服务器进行身份验证的基于JEE 6的Web应用程序应用安全机制。 目的&#x…

mysql 一致性hash_一致性hash算法在分表分库中的应用

一致性hash算法结构图 分表分库结构图 可进行循环冗余存储&#xff0c;顺时针存储到下一个物理节点(非虚拟节点)package com.haiziwang.platform.kmcsms.route.algorithm;import java.util.Collection;import java.util.SortedMap;import java.util.TreeMap;/*** 一致性Hash算法…

生产中的性能分析

生产中的性能分析 如果您在Java应用程序的性能方面遇到了一些严重问题&#xff0c;那么很可能您会知道线程分析的价值。 但是您知道应该使用哪个分析器吗&#xff1f; 探查器使用两种基本技术-采样和仪器。 采样分析器 采样探查器包括定期向JVM询问所有当前活动线程的当前执行…

mysql用com_MySQL 使用教程

关于 MySQLMySQL 是最流行的开源数据库。本文简明的讲解了 MySQL 如何下载安装到使用的整个过程。MySQL 支持多种特性&#xff1a;使用 C和 C编写&#xff0c;并使用了多种编译器进行测试&#xff0c;保证了源代码的可移植性。支持 AIX、FreeBSD、HP-UX、Linux、Mac OS、Novell…

c++ 一维数组长度_每天一点C / 一维数组和指针

哈喽&#xff0c;我是老吴&#xff0c;继续记录我的学习心得。每天一点系列是我对微习惯的践行。现在能做到每天一点 C&#xff0c;将来就会有更多的每天一点系列&#xff0c;没人规定嵌入式软件工程师就只能学习 C 语言和折腾 Linux&#xff0c;不要给自己设限。为什么是每天一…

设计模式 工厂方法_工厂设计模式–一种有效的方法

设计模式 工厂方法如您所知&#xff0c;“工厂方法模式”或俗称“工厂设计模式”是“创意设计模式”类别下的一种设计模式。 模式背后的基本原理是&#xff0c;在运行时&#xff0c;我们根据传递的参数获得类似类型的对象。 关于这种模式的文章很多&#xff0c;开发人员可以通过…