fengzhizi0 2009-05-25
因为系统需要,添加报表功能,瞄上了birt,学习之,入门教程看了一大堆,还好,多种数据源支持,对于sql还没精通,看着一大堆sql还有点犯难,所以,xml数据源成了我的首选,仔细研究之下,发现原来birt提供的初级功能原来很少,报表经常需要替换数据源来显示其不同的内容,而传统的设置xml数据源只是事前指定好xml文件,或url,google了一下,基本没有发现可用的例子,郁闷之,自己琢磨了一周几乎,更郁闷的是其实问题早有了答案,就载在acegi的权限控制之上一直未看到胜利的曙光下面把自己动态修改xml数据源的成功发上来我用的是webwork,其他用户请酌情修改相应参数
这个是用来view报表的action需要传入的参数是
reban.reportName=报表文件的文件名
rbean.xmlDataUrl=报表xmldatasourceurl,可以是stream,或xxx.xml之类的,输入浏览器能显示xml即可
BirtReportViewer.java
package com.morepower.controller.birt; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import org.eclipse.birt.report.engine.api.EngineConstants; import org.eclipse.birt.report.engine.api.HTMLRenderOption; import org.eclipse.birt.report.engine.api.HTMLServerImageHandler; import org.eclipse.birt.report.engine.api.IHTMLRenderOption; import org.eclipse.birt.report.engine.api.IRenderOption; 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.model.api.DataSourceHandle; import org.eclipse.birt.report.model.api.ElementFactory; import org.eclipse.birt.report.model.api.OdaDataSetHandle; import org.eclipse.birt.report.model.api.OdaDataSourceHandle; import org.eclipse.birt.report.model.api.ReportDesignHandle; import org.eclipse.birt.report.model.api.TableHandle; import org.eclipse.birt.report.model.api.activity.SemanticException; import com.morepower.controller.AbstractAction; import com.morepower.util.BirtEngine; import com.morepower.view.BirtReporterBean; import com.opensymphony.webwork.ServletActionContext; import com.opensymphony.webwork.interceptor.ServletRequestAware; public class BirtReportViewer extends AbstractAction implements ServletRequestAware { /** * */ private static final long serialVersionUID = 1L; private static String REPORT_DIR = "birt-reportors"; private static String REPORT_IMAGE_DIR = "images"; private IReportEngine birtReportEngine = null; private HttpServletRequest request; private BirtReporterBean rbean; private InputStream reportStream; private static String DATASOURCE_NAME = "DataSource"; private static String DATASET_NAME = "DataSet"; private static String QueryText = ""; public InputStream getReportStream() { return this.reportStream; } @Override public String execute() throws Exception { // get report name and launch the engine // resp.setContentType("text/html"); // resp.setContentType( "application/pdf" ); // resp.setHeader ("Content-Disposition","inline; filename=test.pdf"); String reportName = rbean.getReportName(); ServletContext sc = ServletActionContext.getServletContext(); birtReportEngine = BirtEngine.getBirtEngine(sc); IReportRunnable design = birtReportEngine.openReportDesign(sc .getRealPath(java.io.File.separator + REPORT_DIR) + java.io.File.separator + reportName); ReportDesignHandle report = (ReportDesignHandle) design .getDesignHandle(); // 只是动态更换数据源即可,不需改变报表的其他结构 // 暂时不支持动态创建表格 // create task to run and render report buildReport(report); IRunAndRenderTask task = birtReportEngine .createRunAndRenderTask(design); task.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY, BirtReportViewer.class.getClassLoader()); // set output options HTMLRenderOption options = new HTMLRenderOption(); options.setImageHandler(new HTMLServerImageHandler()); options.setImageDirectory(sc.getRealPath(java.io.File.separator + REPORT_IMAGE_DIR)); options.setBaseImageURL(request.getContextPath() + java.io.File.separator + REPORT_IMAGE_DIR); options.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_HTML); options.setOption(IRenderOption.HTML_PAGINATION, Boolean.TRUE); options.setOption(IHTMLRenderOption.MASTER_PAGE_CONTENT, new Boolean( true)); // options.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_PDF); options.setOption(HTMLRenderOption.HTML_ENABLE_METADATA, Boolean.FALSE); ByteArrayOutputStream bout = new ByteArrayOutputStream(); //String renderstr = bout.toString("utf-8"); options.setOutputStream(bout); task.setRenderOption(options); /* * 另外一种方案,直接在action中构造inputStream 对像,但这样 * 可能导致你的报表viewer与具体业务类耦合! * task.getAppContext().put(org.eclipse.datatools.enablement.oda.xml.Constants.APPCONTEXT_INPUTSTREAM, reportStream); task.getAppContext().put(org.eclipse.datatools.enablement.oda.xml.Constants.APPCONTEXT_CLOSEINPUTSTREAM, Boolean.TRUE);*/ // run report task.run(); task.close(); reportStream = new ByteArrayInputStream(bout.toByteArray()); return SUCCESS; } /** * 清除原有的数据源 */ protected void clearDataSource(ReportDesignHandle designHandle) { //DataSourceHandle dsh = designHandle.findDataSource(DATASOURCE_NAME); //dsh.drop(); int count = designHandle.getDataSources().getCount(); try { for (int i = 0; i < count; i++) designHandle.getDataSources().drop(i); } catch (SemanticException e) { log.error(e); e.printStackTrace(); } } /** * 清除原有的数据集 */ protected void clearDataSet(ReportDesignHandle designHandle) { getQueryText(designHandle); int count = designHandle.getDataSets().getCount(); try { for (int i = 0; i < count; i++) designHandle.getDataSets().drop(i); } catch (SemanticException e) { log.error(e); e.printStackTrace(); } } /** * */ protected void getQueryText(ReportDesignHandle designHandle) { QueryText = (String) designHandle.getDataSets().get(0).getProperty( "queryText"); } protected void buildReport(ReportDesignHandle designHandle) { try { ElementFactory designFactory = designHandle.getElementFactory(); buildDataSource(designFactory, designHandle); buildDataSet(designFactory, designHandle); TableHandle table = (TableHandle) designHandle.getBody().get(0); table.setDataSet(designHandle.findDataSet(DATASET_NAME)); } catch (SemanticException e) { log.error(e); e.printStackTrace(); } } protected void buildDataSource(ElementFactory designFactory, ReportDesignHandle designHandle) throws SemanticException { clearDataSource(designHandle); OdaDataSourceHandle dsHandle = designFactory.newOdaDataSource( DATASOURCE_NAME, "org.eclipse.birt.report.data.oda.xml" ); /*dsHandle.setProperty( "odaDriverClass", "com.mysql.jdbc.Driver" ); dsHandle.setProperty( "odaURL", "jdbc:mysql://localhost/stat" ); dsHandle.setProperty( "odaUser", "root" ); dsHandle.setProperty( "odaPassword", "" );*/ dsHandle.setProperty("FILELIST", rbean.getXmlDataUrl()); designHandle.getDataSources().add(dsHandle); } protected void buildDataSet(ElementFactory designFactory, ReportDesignHandle designHandle) throws SemanticException { clearDataSet(designHandle); OdaDataSetHandle dsHandle = designFactory.newOdaDataSet( DATASET_NAME, //"org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" ); /* OdaDataSetHandle dsHandle = designFactory.newOdaDataSet(DATASET_NAME,*/ "org.eclipse.birt.report.data.oda.xml.dataSet"); dsHandle.setPrivateDriverProperty("XML_FILE", rbean.getXmlDataUrl()); dsHandle.setPrivateDriverProperty("MAX_ROW", "-1"); dsHandle.setQueryText(QueryText); dsHandle.setDataSource(DATASOURCE_NAME); designHandle.getDataSets().add(dsHandle); } @Override public void setServletRequest(HttpServletRequest arg0) { request = arg0; } @Override public void destory() { BirtEngine.destroyBirtEngine(); } public BirtReporterBean getRbean() { return rbean; } public void setRbean(BirtReporterBean rbean) { this.rbean = rbean; } @Override public void initilize() { try { log.info("报表系统初始化中............"); BirtEngine.initBirtConfig(); REPORT_DIR = BirtEngine.getBirtReportorProperty("report_dir"); REPORT_IMAGE_DIR = BirtEngine .getBirtReportorProperty("report_image_dir"); DATASOURCE_NAME = "DataSource"; DATASET_NAME = "DataSet"; } catch (Exception e) { e.printStackTrace(); log.error(e); } } }
BirtEngine.java
package com.morepower.util; import java.io.InputStream; import java.io.IOException; import java.util.Properties; import java.util.logging.Level; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.birt.report.engine.api.EngineConfig; import org.eclipse.birt.report.engine.api.IReportEngine; import javax.servlet.*; import org.eclipse.birt.core.framework.PlatformServletContext; import org.eclipse.birt.core.framework.IPlatformContext; import org.eclipse.birt.core.framework.Platform; import org.eclipse.birt.core.exception.BirtException; import org.eclipse.birt.report.engine.api.IReportEngineFactory; public class BirtEngine { private static IReportEngine birtEngine = null; private static Properties configProps = new Properties(); private final static String configFile = "BirtConfig.properties"; protected final static Log log = LogFactory.getLog(BirtEngine.class); public static synchronized void initBirtConfig() { loadEngineProps(); } public static synchronized IReportEngine getBirtEngine(ServletContext sc) { if (birtEngine == null) { EngineConfig config = new EngineConfig(); if (configProps != null) { String logLevel = configProps.getProperty("logLevel"); Level level = Level.OFF; if ("SEVERE".equalsIgnoreCase(logLevel)) { level = Level.SEVERE; } else if ("WARNING".equalsIgnoreCase(logLevel)) { level = Level.WARNING; } else if ("INFO".equalsIgnoreCase(logLevel)) { level = Level.INFO; } else if ("CONFIG".equalsIgnoreCase(logLevel)) { level = Level.CONFIG; } else if ("FINE".equalsIgnoreCase(logLevel)) { level = Level.FINE; } else if ("FINER".equalsIgnoreCase(logLevel)) { level = Level.FINER; } else if ("FINEST".equalsIgnoreCase(logLevel)) { level = Level.FINEST; } else if ("OFF".equalsIgnoreCase(logLevel)) { level = Level.OFF; } config.setLogConfig(configProps.getProperty("logDirectory"), level); } //sc.getRealPath("")+java.io.File.separator+configProps.getProperty("engine_home") config.setEngineHome(""); IPlatformContext context = new PlatformServletContext(sc); log.info(context.getPlatform()); config.setPlatformContext(context); 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(); } private static void loadEngineProps() { try { // Config File must be in classpath ClassLoader cl = Thread.currentThread().getContextClassLoader(); InputStream in = cl.getResourceAsStream(configFile); configProps.load(in); in.close(); } catch (IOException e) { e.printStackTrace(); } } public static String getBirtReportorProperty(String key){ return configProps.getProperty(key); } }
使用方法
在浏览器中输入url
http://localhost:8800/stat/birtviewer.action?rbean.reportName=index.rptdesign&rbean.xmlDataUrl=http://localhost:8800/stat/armrptxml.action?reporter.id=008a81b61c30d47e011c4f446718001b
对报表熟悉的人应该知道这个方法