懒惰地将JasperReports .jrxml编译为.jasper

时间:2008-11-24 14:41:11

标签: java spring jasper-reports

我使用Spring框架提供的JasperReportsMultiFormatView类的Jasper报告。在创建Spring应用程序上下文时,此类负责将源.jrxml文件编译为其编译的.jasper格式。

但是,这个编译过程确实减慢了应用程序的启动时间。是否有可能延迟编译报告而不是在启动时编译,即报告仅在第一次请求时编译?

如果无法做到这一点,欢迎提出如何减少/消除报告编制时间的替代建议。当然,我可以强制要求编译的报告必须与.jrxml文件一起检入SVN,但在某人(很可能是我)忘记之前,这只是时间问题。

干杯, 唐

2 个答案:

答案 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;
}

}

相关问题