简体   繁体   English

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

[英]lazily compile JasperReports .jrxml to .jasper

I use Jasper reports with the JasperReportsMultiFormatView class provided by the Spring framework. 我使用Jasper报告与Spring框架提供的JasperReportsMultiFormatView类。 This class takes care of compiling the source .jrxml files to their compiled .jasper format when the Spring application context is created. 在创建Spring应用程序上下文时,此类负责将源.jrxml文件编译为其编译的.jasper格式。

However, this compilation process is really slowing down the application startup time. 但是,此编译过程实际上减慢了应用程序启动时间。 Is it possible for the reports to be lazily compiled instead of compiled at startup time, ie a report is only compiled the first time it is requested? 是否有可能延迟编译报告而不是在启动时编译,即报告仅在第一次请求时编译?

If this is not possible, alternative suggestions for how I can reduce/eliminate the report compilation time would be welcome. 如果无法做到这一点,欢迎提出如何减少/消除报告编制时间的替代建议。 Of course, I could mandate that the compiled reports must be checked into SVN along with the .jrxml files, but it's only a matter of time, before someone (most likely me) forgets. 当然,我可以强制要求编译的报告必须与.jrxml文件一起检入SVN,但在某人(很可能是我)忘记之前,这只是时间问题。

Cheers, Don 干杯,唐

I, like you, started out with the Spring helper classes for Jasper Reports but quickly abandoned them as being too coarse-grained and inflexible, which is unusual for Spring. 我和你一样,开始使用Jasper Reports的Spring辅助类,但很快就放弃了它们,因为它太粗糙和不灵活,这对于Spring来说是不寻常的。 Its like they were added as an afterthought. 就像它们被添加为事后的想法一样。

The big problem I had with them was that once they were compiled, it required an appserver bounce to put in new versions. 我遇到的一个大问题是,一旦编译完成,它就需要一个appserver弹出来放入新版本。 In my case, I was after a solution whereby I could change them on disk and they'd recompile, much like how JSPs normally work (if you don't turn this feature off, which many production sites would). 在我的情况下,我正在寻找一个解决方案,我可以在磁盘上更改它们并重新编译,就像JSP正常工作一样(如果你不关闭这个功能,很多生产网站会这样做)。

Alternatively, I wanted to be able to store the jrxml files in a database or run the reports remotely (eg through the JasperServer web services interface). 或者,我希望能够将jrxml文件存储在数据库中或远程运行报告(例如,通过JasperServer Web服务接口)。 The Spring classes just made it all but impossible to implement such features. Spring类只是使得实现这些功能几乎不可能。

So my suggestion to you is: roll your own. 所以我给你的建议是:滚动你自己。 There are a couple of gotchas along the way though, which I'll share with you to minimize the pain. 一路上有几个陷阱,我将与你分享,以尽量减少痛苦。 Some of these things aren't obvious from the documentation. 其中一些内容在文档中并不明显。

The first thing you'll need is a jasper reports compiler. 您需要的第一件事是jasper报告编译器。 This is responsible for compiling a jrxml file into a JasperDesign object. 这负责将jrxml文件编译为JasperDesign对象。 There are several implemenations of this but the one you want is the JRJdtCompiler. 有几个实现,但你想要的是JRJdtCompiler。 You can instantiate and inject this in a Spring application context. 您可以在Spring应用程序上下文中实例化并注入它。 Avoid others like the beanshell compiler since running the report as a large beanshell script is not particularly fast or efficient (I found this out the hard way before I knew any better). 避免像beanhell编译器这样的其他人,因为运行报告作为一个大的beanhell脚本并不是特别快速或有效(在我知道更好之前我发现了这一点)。

You will need to include the jar files for the JRJdtCompiler. 您需要包含JRJdtCompiler的jar文件。 I think the full Jasper Reports dist includes this jar. 我认为完整的Jasper Reports dist包括这个罐子。 Its an eclipse product. 它是一个日食产品。

You can store the JasperDesign anywhere you like (HttpSession, servlet context or whatever). 您可以将JasperDesign存储在任何您喜欢的地方(HttpSession,servlet context或其他)。 The fillReport() method is the primary one you're interested in. It creates a JasperPrint object, which is an instance of a run report. fillReport()方法是您感兴趣的主要方法。它创建一个JasperPrint对象,它是运行报告的一个实例。 Parameters are just passed in as a Map. 参数只是作为Map传入。

Now to create a versino in HTML, PDF, etc, you need to export it. 现在要用HTML,PDF等创建一个versino,你需要导出它。 You use classes like the JRHtmlExporter and JRPdfExporter to do this. 您可以使用JRHtmlExporter和JRPdfExporter之类的类来执行此操作。 They require certain parameters. 它们需要某些参数。 The tricky one is the HTML exporter because HTML obviously doesn't include the images. 棘手的是HTML导出器,因为HTML显然不包含图像。 Jasper includes an ImageServlet class that fetches these from the session (where the JRHtmlExporter has put them) but you have to get the config of both the HTML exporter and image servlet just right and its hard to tell where you're going wrong. Jasper包含一个ImageServlet类,它从会话中获取这些类(JRHtmlExporter放置它们)但是你必须得到HTML导出器和图像servlet的配置恰到好处并且很难分辨出你出错的地方。

I don't remember the specifics of it but theres an example of all this in the Jasper Reports Definitive Guide , which I'd highly recommend you get if you're spending anytime at all with this product. 我不记得它的具体细节,但是Jasper Reports权威指南中的所有这些都是一个例子,如果你随时都在使用这个产品,我强烈建议你这样做。 Its fairly cheap at US$50. 它相当便宜50美元。 You could get the annual subscription too but in the 18+ months I've seen it I haven't seen a single change. 您也可以获得年度订阅,但在18个多月的时间里,我看到它并没有看到任何变化。 Just buy the new version when it comes out if you need it (which you probably won't). 只要你需要它就可以购买新版本(你可能不会这样做)。

Hope this helps. 希望这可以帮助。

The report is compiled the first time its run, put a break point in AbstractJasperReportsView protected final JasperReport loadReport(Resource resource) method to confirm this. 该报告是在其第一次运行时编译的,在AbstractJasperReportsView保护最终的JasperReport loadReport(Resource resource)方法中确定了这一点。

However the above post is correct that you'll need to extend the JasperReportsMultiFormatView if you want to provide any specific compilation process. 但是上面的帖子是正确的,如果你想提供任何特定的编译过程,你需要扩展JasperReportsMultiFormatView。

A great example of dynamic compilation is here: http://javanetspeed.blogspot.com/2013/01/jasper-ireport-with-java-spring-and.html 动态编译的一个很好的例子是: 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;
}

} }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM