2

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

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

如果这是不可能的,我将欢迎有关如何减少/消除报告编译时间的替代建议。当然,我可以要求编译的报告必须与 .jrxml 文件一起检查到 SVN 中,但这只是时间问题,有人(很可能是我)忘记了。

干杯,唐

4

2 回答 2

8

我和你一样,从 Jasper Reports 的 Spring 辅助类开始,但很快就放弃了它们,因为它们过于粗粒度和不灵活,这对 Spring 来说是不寻常的。就像他们是事后才添加的。

我对它们的最大问题是,一旦它们被编译,它需要应用服务器反弹才能放入新版本。就我而言,我正在寻求一个解决方案,我可以在磁盘上更改它们并重新编译,就像 JSP 的正常工作方式一样(如果您不关闭此功能,许多生产站点都会这样做)。

或者,我希望能够将 jrxml 文件存储在数据库中或远程运行报告(例如通过 JasperServer Web 服务接口)。Spring 类使实现这些功能几乎不可能。

所以我给你的建议是:自己动手。不过,在此过程中存在一些问题,我将与您分享以最大程度地减少痛苦。其中一些事情在文档中并不明显。

您需要的第一件事是 jasper 报告编译器。这负责将 jrxml 文件编译成 JasperDesign 对象。有几种实现方式,但您想要的是 JRJdtCompiler。您可以在 Spring 应用程序上下文中实例化和注入它。避免使用 beanshell 编译器之类的其他编译器,因为将报告作为大型 beanshell 脚本运行并不是特别快或高效(在我知道更好之前,我发现了这一点很困难)。

您需要包含 JRJdtCompiler 的 jar 文件。我认为完整的 Jasper Reports dist 包括这个 jar。它是一个日食产品。

您可以将 JasperDesign 存储在您喜欢的任何位置(HttpSession、servlet 上下文或其他)。fillReport() 方法是您感兴趣的主要方法。它创建一个 JasperPrint 对象,它是运行报告的一个实例。参数只是作为 Map 传入。

现在要以 HTML、PDF 等格式创建 versino,您需要将其导出。您可以使用 JRHtmlExporter 和 JRPdfExporter 之类的类来执行此操作。它们需要某些参数。棘手的是 HTML 导出器,因为 HTML 显然不包含图像。Jasper 包含一个 ImageServlet 类,该类从会话(JRHtmlExporter 放置它们的位置)中获取这些内容,但是您必须正确配置 HTML 导出器和图像 servlet,并且很难判断哪里出错了。

我不记得它的细节,但在Jasper Reports Definitive Guide中有一个所有这些的例子,如果你在任何时候都花在这个产品上,我强烈建议你去看看。它相当便宜,50美元。您也可以获得年度订阅,但在我看到它的 18 个多月里,我没有看到任何变化。如果您需要,只需在新版本发布时购买(您可能不会)。

希望这可以帮助。

于 2008-11-30T02:27:18.947 回答
1

报告在第一次运行时编译,在 AbstractJasperReportsView protected final JasperReport loadReport(Resource resource) 方法中放置一个断点来确认这一点。

但是上面的帖子是正确的,如果您想提供任何特定的编译过程,您需要扩展 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;
}

}

于 2013-01-30T19:02:42.120 回答