2008-11-24 98 views
2

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

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

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

干杯, 唐

回答

8

我,像你一样,开始了以春季助手类Jasper报表,但很快就放弃了他们作为过于粗粒度和不灵活的,这是不寻常的春天。它就像是事后添加的一样。

我遇到的最大问题是,一旦编译完成,它需要应用程序服务器反弹才能放入新版本。在我的情况下,我是在解决方案后,我可以在磁盘上更改它们,并重新编译,就像JSP正常工作的方式一样(如果不关闭此功能,那么许多生产站点会这样做)。

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

所以我给你的建议是:滚动你自己的。虽然有一些陷阱,但我会与你分享,以减少疼痛。其中一些内容从文档中不明显。

你需要的第一件事是一个jasper报告编译器。这负责将jrxml文件编译为JasperDesign对象。这有几个实现,但你想要的是JRJdtCompiler。你可以在Spring应用程序上下文中实例化并注入它。因为将报表作为一个大的beanshell脚本运行并不是特别快速或有效的(在我知道任何更好之前,我发现这很困难)。

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

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

现在要创建一个HTML,PDF等版本,你需要导出它。您可以使用类似JRHtmlExporter和JRPdfExporter的类来执行此操作。他们需要某些参数。棘手的是HTML输出器,因为HTML显然不包含图像。 Jasper包含一个ImageServlet类,可以从会话中获取这些信息(JRHtmlExporter放置它们的地方),但是您必须获取HTML导出器和图像servlet的配置,并且很难告诉您哪里出错。

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

希望这会有所帮助。

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

}