BIRT的文档生成,渲染技术
关于编写viewer,关键在于使用ReportEngine API,这个在birt官方文档上有很详细的描述。 这里将几个主要环节总结一下:
- 启动ReportEngine
这里需要注意启动ReportEngine的开销问题和图片链的协议的问题。使用IReportEngineFactory比每次new一个出来性能方面要好很多。使用HTMLEmitterConfig可以使得生成的HTML报表中的图片的src指向一个web资源而非file资源。

public?IReportEngine?getEngine()?...{
????try?...{
??????if(platformContext?==?null)?...{
????????platformContext?=?new?PlatformServletContext(servletContext);
??????}
??????engineConfig?=?new?EngineConfig();
??????engineConfig.setEngineHome(
??????????servletContext.getRealPath("/WEB-INF/platform/"));
??????//?要求ENGINE?HOME?位于WEB-INF/Platform
??????engineConfig.setPlatformContext(platformContext);?
??????//This?call?sets?the?Log?directory?name?and?level
??????engineConfig.setLogConfig(getLogDir(),?Level.FINE);
??????
??????//设置Emitter,渲染HTML的时候,image的地址是HTTP协议而不是File协议
??????HTMLEmitterConfig?emitterConfig?=?new?HTMLEmitterConfig(?);
??????emitterConfig.setActionHandler(new?HTMLActionHandler());
??????HTMLServerImageHandler?imageHandler?=?new?HTMLServerImageHandler();
??????emitterConfig.setImageHandler(imageHandler);
??????engineConfig.getEmitterConfigs().put("html",?emitterConfig);
??????
??????//设置日志level
??????engineConfig.setLogConfig(getLogDir(),?Level.WARNING);
??????//启动Platform,创建ReportEngine
??????Platform.startup(engineConfig);
??????IReportEngineFactory?factory?=?(IReportEngineFactory)?Platform
??????????.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
??????engine?=?factory.createReportEngine(engineConfig);
??????engine.changeLogLevel(Level.WARNING);
??????
??????log.debug("A?new?engine?startup.");
????}?catch?(BirtException?e)?...{
??????e.printStackTrace();
????}
????return?engine;
??}运行报表我理解为编译报表文件。BIRT在渲染报表之前,要将报表编译为.rptdocument,再根据这个文件将报表渲染为HTML格式或PDF格式。编译报表使用IRunTask:

protected?void?run(String?rptDesign)?...{
????assert?(context?!=?null);
????IReportEngine?engine?=?context.getEngine();
????//?Open?a?report?design
????IReportRunnable?design?=?null;
????try?...{
??????design?=?engine.openReportDesign(context
??????????.getFullRptDesignFilename(rptDesign));
??????//?Create?task?to?run?the?report?-?use?the?task?to
??????//?execute?the?report?and?save?to?disk.
??????IRunTask?task?=?engine.createRunTask(design);
??????String?doc?=?context.getFullRptDocumentFilename(rptDesign);
??????//?run?the?report?and?destroy?the?engine
??????task.run(doc);
??????
??????log.debug("save?rpt?design?to?"?+?doc);
??????task.close();
????}?catch?(EngineException?e)?...{
??????e.printStackTrace();
????}
??}渲染报表BIRT支持HTML格式和PDF格式,这两种报表生成的过程相同,只是设置不同的RenderContext和RenderOptions。我们把相同的部分提取为父类的公共方法,不同的部分留给子类实现:
IReportDocument?iReportDocument?=?engine.openReportDocument(docFilename);
??????//Create?Render?Task
??????IRenderTask?task?=?engine.createRenderTask(iReportDocument);
??????task.addScriptableJavaObject("jsBirtObject",?
??????????getScriptableObject(scriptObj));
??????if(params?!=?null?&&?!params.isEmpty())?...{
????????task.setParameterValues(params);
??????}
??????setRenderContext(task);?//设置Render?Context,具体由子类实现
??????setRenderOptions(task,?out);?//设置Render?Options,具体由子类实现
??????task.render();
??????task.close();
????}?catch?(EngineException?e)?...{
??????e.printStackTrace();
????}?finally?...{
??????engine.shutdown();
????}渲染PDF和HTML报表
??/**?*//**
???*?@see?AbstractBirtReportParser#setRenderContext(IRenderTask)
???*/
??@Override
??protected?void?setRenderContext(IRenderTask?task)?...{
????PDFRenderContext?renderContext?=?new?PDFRenderContext();
????renderContext.setEmbededFont(true);????
????HashMap?contextMap?=?new?HashMap();
????contextMap.put(?EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT,?renderContext);
????task.setAppContext(?contextMap?);????????
??}

??/**?*//**
???*?@see?AbstractBirtReportParser#setRenderOptions(IRenderTask,?OutputStream)
???*/
??@Override
??protected?void?setRenderOptions(IRenderTask?task,?OutputStream?out)?...{
????RenderOptionBase?options?=?new?RenderOptionBase();
????options.setOutputStream(out);
????options.setOutputFormat(RenderOptionBase.OUTPUT_FORMAT_PDF);
????task.setRenderOption(options);
??}HTML我们要生成一个HTML的一部分,而非包含<html/>标记的完整的HTML文档

??/**?*//**
???*?@see?AbstractBirtReportParser#setRenderContext(IRenderTask)
???*/
??@Override
??protected?void?setRenderContext(IRenderTask?task)?...{
????HTMLRenderContext?renderContext?=?new?HTMLRenderContext();
????renderContext.setBaseURL(context.getBaseURL());????????
???//You?must?define?HTMLServerImageHandler?to?use?a?URL
????renderContext.setBaseImageURL(context.getBaseImageURL());
????//renderContext.setImageDirectory("myimages");
????renderContext.setImageDirectory(context.getImageDirectory());
????renderContext.setSupportedImageFormats("JPG;PNG");
????HashMap?contextMap?=?new?HashMap();
????contextMap.put(?EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT,?renderContext);
????task.setAppContext(?contextMap?);????
??}

??/**?*//**
???*?@see?AbstractBirtReportParser#setRenderOptions(oIRenderTask,?OutputStream)
???*/
??@Override
??protected?void?setRenderOptions(IRenderTask?task,?OutputStream?out)?...{
????HTMLRenderOption?options?=?new?HTMLRenderOption();
????options.setOutputStream(out);
????options.setEmbeddable(true);
????task.setRenderOption(options);???
??}