建国's profile小白的生活PhotosBlogLists Tools Help

Blog


    June 25

    BIRT的文档生成,渲染技术

    关于编写viewer,关键在于使用ReportEngine API,这个在birt官方文档上有很详细的描述。 这里将几个主要环节总结一下:
    1. 启动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;
        }
    2. 运行报表
      我理解为编译报表文件。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();
          }

        }
    3. 渲染报表
      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();
          }
    4. 渲染PDF和HTML报表
      • PDF
          /** *//**
           * 
        @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);   
          }