我使用Spring框架提供的JasperReportsMultiFormatView类的Jasper报告。在创建Spring应用程序上下文时,此类负责将源.jrxml文件编译为其编译的.jasper格式。
但是,这个编译过程确实减慢了应用程序的启动时间。是否有可能延迟编译报告而不是在启动时编译,即报告仅在第一次请求时编译?
如果无法做到这一点,欢迎提出如何减少/消除报告编制时间的替代建议。当然,我可以强制要求编译的报告必须与.jrxml文件一起检入SVN,但在某人(很可能是我)忘记之前,这只是时间问题。
干杯, 唐
答案 0 :(得分:8)
我和你一样,开始使用Jasper Reports的Spring辅助类,但很快就放弃了它们,因为它太粗糙和不灵活,这对于Spring来说是不寻常的。它就像是事后补充一样。
我遇到的一个大问题是,一旦编译完成,它就需要一个appserver弹出来放入新版本。在我的情况下,我找到了一个解决方案,我可以在磁盘上更改它们并重新编译,就像JSP正常工作一样(如果你不关闭这个功能,很多生产网站会这样做)。
或者,我希望能够将jrxml文件存储在数据库中或远程运行报告(例如,通过JasperServer Web服务界面)。 Spring类只是实现了这些功能,但几乎不可能。
所以我给你的建议是:滚动你自己。一路上有几个陷阱,我将与你分享,以尽量减少痛苦。其中一些内容在文档中并不明显。
您需要的第一件事是jasper报告编译器。这负责将jrxml文件编译为JasperDesign对象。有几个实现,但你想要的是JRJdtCompiler。您可以在Spring应用程序上下文中实例化并注入它。避免像beanshell编译器这样的其他人,因为运行报告作为一个大的beanhell脚本并不是特别快速或有效(在我知道更好之前我发现了这一点)。
您需要包含JRJdtCompiler的jar文件。我认为完整的Jasper Reports dist包括这个罐子。它是一个日食产品。
您可以将JasperDesign存储在任何您喜欢的地方(HttpSession,servlet上下文或其他)。 fillReport()方法是您感兴趣的主要方法。它创建一个JasperPrint对象,它是运行报告的一个实例。参数只是作为Map传入。
现在要在HTML,PDF等中创建一个versino,您需要导出它。您可以使用JRHtmlExporter和JRPdfExporter之类的类来执行此操作。它们需要某些参数。棘手的是HTML导出器,因为HTML显然不包含图像。 Jasper包含一个ImageServlet类,它从会话中获取这些内容(JRHtmlExporter放置它们),但是你必须正确地获取HTML导出器和图像servlet的配置,并且很难分辨出你出错的地方。
我不记得它的具体细节,但是Jasper Reports Definitive Guide中的所有这些都是一个例子,如果你在这个产品上花费任何时间,我强烈建议你这样做。它相当便宜50美元。您也可以获得年度订阅,但在18个多月的时间里,我看到它并没有看到任何变化。只要你需要它就可以购买新版本(你可能不会这样做)。
希望这有帮助。
答案 1 :(得分:1)
报告是在第一次运行时编译的,在AbstractJasperReportsView保护最终的JasperReport loadReport(资源资源)方法中设置了一个断点来确认这一点。
但是上面的帖子是正确的,如果你想提供任何特定的编译过程,你需要扩展JasperReportsMultiFormatView。
动态编译的一个很好的例子是:http://javanetspeed.blogspot.com/2013/01/jasper-ireport-with-java-spring-and.html
import net.sf.jasperreports.engine.JasperReport;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView;
public class DynamicJasperReportsMultiFormatView extends JasperReportsMultiFormatView {
private static final Logger LOG = Logger.getLogger(DynamicJasperReportsMultiFormatView.class);
/**
* The JasperReport that is used to render the view.
*/
private JasperReport jasperReport;
/**
* The last modified time of the jrxml resource file, used to force compilation.
*/
private long jrxmlTimestamp;
@Override
protected void onInit() {
jasperReport = super.getReport();
try {
String url = getUrl();
if (url != null) {
jrxmlTimestamp = getApplicationContext().getResource(url).getFile().lastModified();
}
} catch (Exception e) {
e = null;
}
}
@Override
protected JasperReport getReport() {
if (this.isDirty()) {
LOG.info("Forcing recompilation of jasper report as the jrxml has changed");
this.jasperReport = this.loadReport();
}
return this.jasperReport;
}
/**
* Determines if the jrxml file is dirty by checking its timestamp.
*
* @return true to force recompilation because the report xml has changed, false otherwise
*/
private boolean isDirty() {
long curTimestamp = 0L;
try {
String url = getUrl();
if (url != null) {
curTimestamp = getApplicationContext().getResource(url).getFile().lastModified();
if (curTimestamp > jrxmlTimestamp) {
jrxmlTimestamp = curTimestamp;
return true;
}
}
} catch (Exception e) {
e = null;
}
return false;
}
}