12.1 报表的工作模式以及相应的部署和配置
虽然为了示例的需要,在前文的第二章讲过BIRT的配置,以及在文本类报表,网格报表,图表中用过birt jsp tag,也做过一些说明。但报表的工作模式,不仅仅包含这两种。实际上,BIRT有五种工作模式,
第一种是用jsp或者javascript访问url,这个url遵循特定的格式,例如url/frameset?__report=&__paraname=paravalue;
第二种方式是在jsp页面中嵌入birt tag;
第三种模式是在servlet或者java class中打开用报表设计器设计的报表,导出一个html,pdf或者其它格式的文档的输出到既定的目录;
第四种是扩展报表展示器birt web viewer,也即是改写birt web viewer的servlet,配置访问路径,并用它来展示先前在报表设计器中设计的报表;
第五种模式即是在java class中利用报表设计API,生成报表设计文档,并用报表引擎API打开并生成html,pdf或者其它格式的文档。
本章先详细说明前文用到的两种工作模式,后面的三种,我们会在第十三章及之后的章节详细描述。
第一种工作模式:url
Url的一个例子如下:
http://localhost:8080/birt/frameset?__report=test.rptdesign&__bookmark=bk&__isreportlet=true
说明:
http://localhost:8080:代表访问的服务器地址
/birt :代表访问的app的根目录
/frameset: 代表访问的servlet的模式,在web.xml中有配置的说明
__report=test.rptdesign&__bookmark=bk&__isreportlet=true 代表访问的参数,其中birt保留的参数以两个下划线开头,例如__report指定报表的名称;__bookmark指定报表的书签;报表参数不需要以__开头。
报表访问servlet的模式,主要有以下几种:
frameset ---- 采用Ajax框架,可以显示工具条,导航条和TOC面板,实现复杂的操作,如分页处理,导出数据,导出报表,打印等。该模式下会自动生成report document文件(预览report design文件)到特定的目录(用户可以用参数指定,也可以定义在web.xml里)。采用Ajax,速度较慢。
run ---- 也采用Ajax框架,但不实现frameset的复杂功能,不会生成临时的report document文件(预览report design文件),也不支持分页,这个主要是应用在BIRT Designer里的preview tab里,可以支持cancel操作,其它不怎么常用。采用Ajax,速度较慢。
preview --- 没有用到Ajax框架,直接调用底层Engine API对报表进行render,把生成的报表内容直接输出到浏览器。这种模式和run模式调用的是相同的Engine API,唯一区别在于run采用Ajax获取报表内容,而preview直接输出到浏览器。如果要支持分页,用户需要在URL上定义__page和__pagerange参数。需要特别说明的是,在这几种预览模式中,preview的速度是最快的。
download --- 用于导出报表数据,当你使用frameset工具条里的导出数据功能时,会用到这个模式。
这个模式会直接调用浏览器的下载功能弹出下载框或者调用默认的下载工具打开下载目录地址指定输入框。
output --- 该模式类似于frameset,会自动生成report document文件(预览report design文件),区别在于output不采用Ajax,而是将生成的报表内容直接输出到浏览器。不支持分页。
下面说说最主要的保留参数的含义:
“__report” 定义要预览的rptdesign文件路径,支持相对路径和绝对路径,相对路径是相对于web.xml中定义的工作目录。
“__document” 定义要预览的rptdocument文件路径,同样支持相对和绝对路径。相对路径是相对于web.xml中定义的工作目录。在同时定义了__report和__document参数时,以__document为优先,如未找到相应的document文件,才会从design文件生成document文件(frameset/output)或是直接去render这个design文件(preview/run)。
“__title” 定义报表显示的标题。
“__showtitle” 是否显示frameset模式下上方的标题部分。true | false
“__toolbar” 是否显示frameset模式下的工具条。true | false
“__navigationbar” 是否显示frameset模式下的导航条。true | false
“__parameterpage” 是否强制弹出或不弹出报表参数对话框。true | false
“__format” 输出报表的格式,默认为html。现在支持:pdf | doc | xls | postscript | ppt
“__locale” 设置Locale信息,如 __locale=zh_CN, 注意必须是国家加语言。
“__bookmark” 置页面要定位的书签名字。
“__page” 指定要输出的报表页数,这个依赖于报表的分页设计(page break)。
“__pagerange” 指定要输出的报表页数范围。如1,3,5-9。
“__clean” BIRT里临时生成的一些文件都是和session相关的,比如临时document文件,还有image文件。这些文件也可以通过session进行管理,这个参数就是指定是否需要在session timeout的时候清除这些临时文件。默认值是true。
Document文件夹用于缓存frameset的文档,session退了之后由系统自动删除,也可由用户删除文件夹,对程序不造成影响。
Logs文件夹用于生成系统出现错误时的日志文件。可以删除。
Report文件夹用于放置rptdesign文件,也可以放置在根目录,由url指定
Scriptlib文件夹用于放置用户自定义的脚本,也可以放置在根目录,由报表配置
WEB-INF文件夹用于配置报表运行时环境的各个参数,第二章已经有非常详细的描述,这儿强调一下JNDI的配置
1.tomcat配置jndi连接池
在 {tomcat目录}\webapps\{项目名}\WEB-INF 中新增context.xml文件,配置代码如下
<?xml version="1.0" encoding="UTF-8"?><Context> <Resource auth="Container" name="jdbc/travel_agency" type="javax.sql.DataSource" maxIdle="5" maxWait="-1" driverClassName="com.mysql.jdbc.Driver" username="itravel" password="709394" url="jdbc:mysql://192.168.1.100/travel_agency?useUnicode=true&characterEncoding=UTF-8" maxActive="10"/></Context>
2.在web.xml中加入配置
<resource-ref> <description>Database Source</description> <res-ref-name>jdbc/travel_agency</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth></resource-ref>
如果weblogic已经配置了连接池(jdbc/myjndi),那么只需要在\{应用名}\WEB-INF 下新建context.xml,用于配置报表访问JNDI,内容如下:
<resource-ref><description>Database Source</description><res-ref-name>jdbc/myjndi</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref>
第二种工作模式jsp tag:
JSP birt tag的一个例子在第五章
<birt:viewer id="birtViewer1" reportDesign="orders.rptdesign" baseURL="<%= request.getContextPath( )%>" pattern="run" height="367" width="645" format="html" frameborder="false" isHostPage="false" isReportlet="true" showParameterPage="false" > </birt:viewer>
在\webapps\WebViewerExample\WEB-INF\tlds\birt.tld中有详细的定义。内容的一小部分如下文所示:
<name>viewer</name> <tag-class>org.eclipse.birt.report.taglib.ViewerTag</tag-class> <body-content>JSP</body-content> <description> The viewer tag is to specify how to import and control BIRT Report Viewer into JSP page. This tag will use Ajax framework to retrieve report content. </description> <attribute> <name>id</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description> Specifies the current viewer id. It should be unique. It can contain number,letter or underline. </description> </attribute> <attribute> <name>pattern</name> <required>false</required> <rtexprvalue>true</rtexprvalue> <description> Specifies which servlet pattern to be used to preview report. Default value is frameset. ( frameset or run ) </description> </attribute>
在此说明如下:
birt标签分为: viewer, report, param,parameterPage,paramDef这四个标签。
一、viewer标签
示例:
<birt:viewer id="1"
pattern="run"
reportDesign="test1.rptdesign"
position="absolute"
width="800"
height="500"
left="50"
top="50"
format="html"
svg="false">
<birt:param name="sample" value="abc"/>
<birt:param name="Cust" value="<%=110%>"/>
</birt:viewer>
id: 必须指定,
pattern: 不一定 要指定,指定运行使用的servlet, 默认为frameset
reportDesign: 指定报表文件名
title : 可选,指定报表的标题,其实这不是设计报表的标题,而是报表运行时显示在报表上面的标题。
isHostPage: 可选,默认为false,指定报表是否全屏显示,此属性设置,则width,height,scrolling 属性作废。
scrolling :可选,是否出现滚动条
position: 可选,报表相对于页面的位置,值为static | absolute | fixed | relative,如果设置了isHostPage,该属性作废。
style : 可选,报表显示的样式,没多说的。,如果设置了isHostPage,该属性作废
width,heigth,top,left: 分别设置报表显示的宽,高,上边距,左边距
frameborder :可选,设置报表所在的iframe是否显示边框,默认不显示。值为yes/no
reportDocument : 可选,指定报表文档,只支持file:url,这样的格式。
reportlet : 可选,使用reportDocument ,可指定这个属性,只是指定reportlet 实例的id, 另frameset不支持此属性。
bookmark : 可选,指定目标书签名称
locale : 指定Locale信息,指定语言环境
svg : 可选,指定是否支持输出svg格式文档。
format : 可选,指定报表的输出格式
pageOverflow : 可选,当输出格式为pdf时,指定页面溢出样式,0 表示自动,1表示实际大小,2表示适合页面的大小
pageNum: 可选,指定是否显示页码
pageRange: 指定页面范围。当运行文档文件时指定这个属性。
resourceFolder : 指定相关的资源文件,默认识别web.xml定义的资源文件夹。
showTitle: 是否显示报表标题,默认为true
showToolBar: 是否显示工具条,默认为true
showNavigationBar: 是否显示导航条,默认为true,但是如果allowPageBreak设置为false,该属性作废。
showParameterPage: 是否显示参数对话框。默认为true,
二、report标签
和view标签差不多,但是report没有使用ajax支持,而是直接将内容显示在页面。 内部应该使用了preview。
另有一个特别的属性reportContainer,有两个可选值,iframe,和div,默认为iframe. 指定使用report的容器。
其他属性和view都差不多。
<birt:report id="2"
reportDesign="test.rptdesign"
position="absolute"
width="400"
height="300"
left="900"
top="100"
format="pdf"
reportContainer="iframe">
<birt:param name="sample" value="abc"/>
</birt:report>
三、param
报表参数相关的标签。
name: 指定报表参数名称
value; 参数值
pattern: 参数格式
displayText: 显示文字
isLocale: 指定参数是否本地化字符
四、parameterPage
配置参数页面。
id : 必选。指定参数页面的id
name : 指定参数页面name,如果isCustom设置为true,则此属性一定要写,且唯一。
isCustom : 指定是否使用用户自定义参数页面。默认为false;
target : 指定请求打开窗口的位置。
其他属性与view相似,给个例子:
<birt:parameterPage id="parameterPage"
pattern="run"
reportDesign="test.rptdesign"
target="myiframe"
width="600"
height="400"
format="html"/>
<iframe name="myiframe" width="600" height="400"></iframe>
五、paramDef
这个标签用来生成参数参数页面定义的参数的html代码。
有以下几个属性
id,name,value,pattern,displayText,isLocale,title,style,cssClass.
<birt:parameterPage
id="report2"
name="page2"
reportDesign="test.rptdesign"
isCustom="true" //指定自定义页面
pattern="frameset">
id: <birt:paramDef id="id" name="id" title="这是设置id的区域"/>
<br><br>
sex: <birt:paramDef id="sex" name="sex"/>
<br><br>
<input type="submit" name="submit" value="Sumbit form"/>
<br><br>
</birt:parameterPage>
假如你的text报表里有两个参数,一个参数为id,另一个参数为sex,这时候假如id是一列值,sex是checkbox.
那么这个参数页面就会把这个id要选择的值显示出来,把sex这个checkbox也显示出来。
第三种工作模式——在servlet或者java class中打开用报表设计器设计的报表,导出一个html,pdf或者其它格式的文档的输出到既定的目录;需要新建JAVA project或者java web project,导入report engine库,也就是birt-runtime-3_7_2\ReportEngine\lib目录下的包,如下:
为了便于大家理解,我把启动平台,打开报表,关闭平台分别放置在一个类的三个方法中,并做了相应的注释:
package birt;import org.eclipse.birt.core.framework.Platform;import org.eclipse.birt.report.engine.api.EngineConfig;import org.eclipse.birt.report.engine.api.HTMLRenderOption;import org.eclipse.birt.report.engine.api.IReportEngine;import org.eclipse.birt.report.engine.api.IReportEngineFactory;import org.eclipse.birt.report.engine.api.IReportRunnable;import org.eclipse.birt.report.engine.api.IRunAndRenderTask;public class HtmlReport{IReportEngine engine=null;EngineConfig config = null;HtmlReport (){}//用于运行报表public void runReport(){try{IReportRunnable design = null;//Open the report designdesign = engine.openReportDesign("d:\\CustomerOrdersFinal.rptdesign");//Create task to run and render the report,IRunAndRenderTask task = engine.createRunAndRenderTask(design);HTMLRenderOption options = new HTMLRenderOption();options.setOutputFileName("D:\\TEST.html");options.setOutputFormat("html");options.setEmbeddable(true);task.setRenderOption(options);task.run();task.close();}catch( Exception ex){ex.printStackTrace();}}//用于启动报表平台public void startPlatform(){try{config = new EngineConfig( );config.setBIRTHome("");//低版本的需要在此指定BIRT engine home地址Platform.startup( config );IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );engine = factory.createReportEngine( config );}catch( Exception e){e.printStackTrace();}}//用于停止报表平台public void stopPlatform(){engine.destroy();Platform.shutdown();}public static void main (String[] args){HtmlReport html = new HtmlReport ();html.startPlatform();System.out.println("Started");html.runReport();html.stopPlatform();System.out.println("Finished");}}
其中已经设计好的报表布局如下:
运行报表,我们会在D盘下看到生成的TEST.html文件,打开内容如下:
第四种工作模式,扩展birt web viewer:
首先我们需要改写birt engine,内容如下:
package birt;import java.util.logging.Level;import javax.servlet.ServletContext;import org.eclipse.birt.core.exception.BirtException;import org.eclipse.birt.core.framework.IPlatformContext;import org.eclipse.birt.core.framework.Platform;import org.eclipse.birt.core.framework.PlatformServletContext;import org.eclipse.birt.report.engine.api.EngineConfig;import org.eclipse.birt.report.engine.api.HTMLActionHandler;import org.eclipse.birt.report.engine.api.HTMLEmitterConfig;import org.eclipse.birt.report.engine.api.HTMLServerImageHandler;import org.eclipse.birt.report.engine.api.IReportEngine;import org.eclipse.birt.report.engine.api.IReportEngineFactory;public class BirtEngine { private static IReportEngine birtEngine = null; public static synchronized void initBirtConfig() { } public static synchronized IReportEngine getBirtEngine(ServletContext sc) { EngineConfig config = new EngineConfig(); config.setLogConfig(sc.getRealPath("\\logs"), Level.FINE); config.setEngineHome(""); IPlatformContext context = new PlatformServletContext(sc); config.setPlatformContext(context); //Register new image handler 解决了读取图片时的路径问题 HTMLEmitterConfig emitterConfig = new HTMLEmitterConfig( ); emitterConfig.setActionHandler( new HTMLActionHandler( ) ); HTMLServerImageHandler imageHandler = new HTMLServerImageHandler( ); emitterConfig.setImageHandler( imageHandler ); config.getEmitterConfigs( ).put( "html", emitterConfig ); //-NLS-1$ try { Platform.startup(config); } catch (BirtException e) { e.printStackTrace(); } IReportEngineFactory factory = (IReportEngineFactory) Platform .createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY); birtEngine = factory.createReportEngine(config); return birtEngine; } public static synchronized void destroyBirtEngine() { if (birtEngine == null) { return; } birtEngine.shutdown(); Platform.shutdown(); birtEngine = null; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }
然后我们在servlet中调用这个自定义的birt engine;
package birt;import java.io.IOException;import java.io.PrintWriter;import java.util.ArrayList;import java.util.Collection;import java.util.Date;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.logging.Logger;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.eclipse.birt.report.engine.api.EngineConstants;import org.eclipse.birt.report.engine.api.HTMLRenderContext;import org.eclipse.birt.report.engine.api.HTMLRenderOption;import org.eclipse.birt.report.engine.api.IGetParameterDefinitionTask;import org.eclipse.birt.report.engine.api.IParameterDefnBase;import org.eclipse.birt.report.engine.api.IReportEngine;import org.eclipse.birt.report.engine.api.IReportRunnable;import org.eclipse.birt.report.engine.api.IRunAndRenderTask;import org.eclipse.birt.report.engine.api.IScalarParameterDefn;public class birtServlet extends HttpServlet { private static final long serialVersionUID = 1L; private IReportEngine birtReportEngine = null; protected static Logger logger = Logger.getLogger("org.eclipse.birt"); public birtServlet () { super(); } public void destroy() { super.destroy(); BirtEngine.destroyBirtEngine(); } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { HashMap parmDetails = new HashMap(); // get report name and launch the engine resp.setContentType("text/html"); // resp.setContentType( "application/pdf" ); // resp.setHeader ("Content-Disposition","inline; filename=test.pdf"); //得到参数并放入paramsList集合 String reportName = req.getParameter("ReportName"); String bm = new String(req.getParameter("bm").getBytes("ISO8859_1"),"GB2312"); String sj1 = req.getParameter("sj1"); String sj2 = req.getParameter("sj2"); List paramsList = new ArrayList(); if (bm != null && !bm.equals("") && !bm.equals("null")) paramsList.add(bm); paramsList.add(sj1); paramsList.add(sj2); ServletContext sc = req.getSession().getServletContext(); this.birtReportEngine = BirtEngine.getBirtEngine(sc); // 设置图片地址 HTMLRenderContext renderContext = new HTMLRenderContext(); renderContext.setBaseImageURL(req.getContextPath() + "\\report\\images"); renderContext.setImageDirectory(sc.getRealPath("\\report\\images")); //logger.log(Level.FINE, "image directory " // + sc.getRealPath("\\report\\images")); //System.out.println(renderContext.getBaseImageURL()); //System.out.println(renderContext.getImageDirectory()); HashMap<String, HTMLRenderContext> contextMap = new HashMap<String, HTMLRenderContext>(); contextMap.put(EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderContext); IReportRunnable design; try { // Open report design design = birtReportEngine.openReportDesign(sc .getRealPath("") + "\\" + reportName); //以下是将报表里的参数和传递进来的参数匹配然后放到parmDetails集合中 IGetParameterDefinitionTask taskParam = birtReportEngine.createGetParameterDefinitionTask( design ); Collection params = taskParam.getParameterDefns( true ); Iterator iter = params.iterator(); Iterator iterList = paramsList.iterator(); // Iterate over all parameters while ( iter.hasNext() && iterList.hasNext() ) { IParameterDefnBase param = (IParameterDefnBase) iter.next( ); // Parameters are not in a group IScalarParameterDefn scalar = (IScalarParameterDefn) param; if(scalar.getName().equals("bm")){ String paramList = (String)iterList.next(); parmDetails.put( scalar.getName(),paramList); //System.out.println(scalar.getName() + " " + paramList); }else{ Date paramList = new Date(); parmDetails.put( scalar.getName(),paramList); //System.out.println(scalar.getName() + " " + paramList); } } taskParam.close(); // // create task to run and render report IRunAndRenderTask task = birtReportEngine .createRunAndRenderTask(design); task.setAppContext(contextMap); task.setParameterValues(parmDetails); // set output options HTMLRenderOption options = new HTMLRenderOption(); options.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_HTML); // options.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_PDF); options.setOutputStream(resp.getOutputStream()); task.setRenderOption(options); // 运行报表 task.run(); task.close(); } catch (Exception e) { e.printStackTrace(); throw new ServletException(e); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } public void init() throws ServletException { }}
最后,配置birt engine的访问地址,在web.xml中配置如下:
<servlet> <servlet-name>birtServlet </servlet-name> <servlet-class>birt.birtServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>birtServlet </servlet-name> <url-pattern>/myBirtFrame</url-pattern> </servlet-mapping>
这样,我们可以以这样的方式访问自己的birt viewer:
http://localhost:8080/birt/myBirtFrame?ReportName=CustomerOrdersFinal.rptdesign
注意:如果是在linux或者unix环境运行,则以上地址的”\\”都必须改成”/”,windows和linux的区别,大家都懂的。
以上参数的访问方式也是需要完善的,后面的章节会详细讲解如何扩展birt web viewer。
第五种方式,运用报表设计API产生报表,运行并输出报表。
下面是一个简单的案例
package birt;import java.io.IOException;import org.eclipse.birt.core.framework.Platform;import org.eclipse.birt.report.model.api.CellHandle;import org.eclipse.birt.report.model.api.DesignConfig;import org.eclipse.birt.report.model.api.DesignElementHandle;import org.eclipse.birt.report.model.api.ElementFactory;import org.eclipse.birt.report.model.api.GridHandle;import org.eclipse.birt.report.model.api.IDesignEngine;import org.eclipse.birt.report.model.api.IDesignEngineFactory;import org.eclipse.birt.report.model.api.ImageHandle;import org.eclipse.birt.report.model.api.LabelHandle;import org.eclipse.birt.report.model.api.ReportDesignHandle;import org.eclipse.birt.report.model.api.RowHandle;import org.eclipse.birt.report.model.api.SessionHandle;import org.eclipse.birt.report.model.api.activity.SemanticException; import com.ibm.icu.util.ULocale;public class SimpleCreate { public static void main( String[] args ) { try { buildReport( ); } catch( IOException e ) { e.printStackTrace(); } catch( SemanticException e ) { e.printStackTrace(); } } // This method shows how to build a very simple BIRT report with a // minimal set of content: a simple grid with an image and a label. static void buildReport() throws IOException, SemanticException { // Create a session handle. This is used to manage all open designs. // Your app need create the session only once. //Configure the Engine and start the Platform DesignConfig config = new DesignConfig( ); config.setProperty("BIRT_HOME", "E:\\birt汉化包\\birt-runtime-3_7_2\\ReportEngine"); IDesignEngine engine = null; try { Platform.startup( config ); IDesignEngineFactory factory = (IDesignEngineFactory) Platform.createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY ); engine = factory.createDesignEngine( config ); } catch( Exception ex ) { ex.printStackTrace(); } SessionHandle session = engine.newSessionHandle( ULocale.ENGLISH ) ; // Create a new report design. ReportDesignHandle design = session.createDesign( ); // The element factory creates instances of the various BIRT elements. ElementFactory efactory = design.getElementFactory( ); // Create a simple master page that describes how the report will appear when printed. // // Note: The report will fail to load in the BIRT designer unless you create a master page. DesignElementHandle element = efactory.newSimpleMasterPage( "Page Master" ); design.getMasterPages( ).add( element ); // Create a grid and add it to the "body" slot of the report design. GridHandle grid = efactory.newGridItem( null, 2 /* cols */, 1 /* row */ ); design.getBody( ).add( grid ); // Note: Set the table width to 100% to prevent the label // from appearing too narrow in the layout view. grid.setWidth( "100%" ); // Get the first row. RowHandle row = (RowHandle) grid.getRows( ).get( 0 ); // Create an image and add it to the first cell. ImageHandle image = efactory.newImage( null ); CellHandle cell = (CellHandle) row.getCells( ).get( 0 ); cell.getContent( ).add( image ); image.setURL( "\"http://img.my.csdn.net/uploads/201301/09/1357690895_3463.png\"" ); // Create a label and add it to the second cell. LabelHandle label = efactory.newLabel( null ); cell = (CellHandle) row.getCells( ).get( 1 ); cell.getContent( ).add( label ); label.setText( "Hello, world!" ); // Save the design and close it. design.saveAs( "d:\\sample.rptdesign" ); design.close( ); System.out.println("Finished"); // We're done! } }
运行,我们即可在D盘看到sample.rptdesign
在设计器中预览这个报表,我们看到:
打开并展示报表见第三种报表运行模式,后面章节会更详细的讲解如何运用报表API生成报表设计文件,并运行产生输出。