第十三章 BIRT报表引擎API及报表API (续)-自定义web BIRT展示器
13.2 自定义BIRT viewer(报表展示器)
前面我们提到了可以通过java定制报表查看器,通过servlet访问webreport,方便系统集成。下面我详细讲解如何实现这个过程:
首先实现自定义报表引擎ReportEngine
package birtbird;import java.io.IOException;import java.io.InputStream;import java.util.Properties;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.EngineConstants;import org.eclipse.birt.report.engine.api.IReportEngine;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";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);}config.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY,Thread.currentThread().getContextClassLoader());config.setEngineHome("");IPlatformContext context = new PlatformServletContext(sc);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.destroy();Platform.shutdown();birtEngine = null;}public Object clone() throws CloneNotSupportedException {throw new CloneNotSupportedException();}private static void loadEngineProps() {try {// Config File must be in classpathClassLoader cl = Thread.currentThread().getContextClassLoader();InputStream in = null;in = cl.getResourceAsStream(configFile);configProps.load(in);in.close();} catch (IOException e) {e.printStackTrace();}}}
再其次实现自定义birtviewer selvlet,下面的代码很重要,直接决定了报表展示器的外观
package birtbird;
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.ArrayList;import java.util.Collection;import java.util.Enumeration;import java.util.HashMap;import java.util.Iterator;import java.util.logging.Logger;
import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;
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;import org.eclipse.birt.report.engine.api.PDFRenderOption;import org.eclipse.birt.report.engine.api.RenderOption;
public class ReportServlet extends HttpServlet {
/** * */ private static final long serialVersionUID = 1L; /** * Constructor of the object. */ private IReportEngine birtReportEngine = null; protected static Logger logger = Logger.getLogger("org.eclipse.birt");
public ReportServlet() { super(); }
/** * Destruction of the servlet. */ public void destroy() { super.destroy(); BirtEngine.destroyBirtEngine(); }
/** * The doGet method of the servlet. * */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("utf-8");
try { String reportName = req.getParameter("ReportName");String baseUrl = req.getContextPath() + "/webReport?ReportName=" + reportName;String imgBaseUrl = req.getContextPath() + "/reports/images";String outFormat = "html";
// 处理页面传过来的参数HashMap<String, String> paramMap = new HashMap<String, String>();Enumeration en = req.getParameterNames();while (en.hasMoreElements()) { String pName = (String) en.nextElement(); String pValue = req.getParameter(pName); if (pName.equals("O_FORMAT")) { outFormat = pValue; } else { paramMap.put(pName, pValue); }}
ServletContext sc = req.getSession().getServletContext();this.birtReportEngine = BirtEngine.getBirtEngine(sc);IReportRunnable design = birtReportEngine.openReportDesign(sc .getRealPath("/reports") + "/" + reportName);
HashMap<String, Object> parameters = new HashMap<String, Object>();// 以打开的报表设计文件为参数,创建一个获取参数的对象IGetParameterDefinitionTask paramTask = birtReportEngine .createGetParameterDefinitionTask(design);// 获取报表设计文件中的参数定义Collection paramDefns = paramTask.getParameterDefns(false);// 为获取的参数定义赋值Iterator iter = paramDefns.iterator();while (iter.hasNext()) { IParameterDefnBase pBase = (IParameterDefnBase) iter.next(); if (pBase instanceof IScalarParameterDefn) { IScalarParameterDefn paramDefn = (IScalarParameterDefn) pBase; String pName = paramDefn.getName();// 报表参数名称 // int pType = paramDefn.getDataType( ); String pValue = paramMap.get(pName);// 页面传过来的值 if (pValue == null) { pValue = ""; } else { baseUrl += "&" + pName + "=" + pValue; } // Object pObject = stringToObject( pType, pValue ); parameters.put(pName, pValue); }}
if (outFormat.equals("html")) {// 页面展示 resp.setContentType("text/html"); HTMLRenderOption htmlOptions = new HTMLRenderOption(); htmlOptions.setOutputFormat(RenderOption.OUTPUT_FORMAT_HTML);
// setup image directory // HTMLRenderContext renderContext = new HTMLRenderContext(); // renderContext.setBaseImageURL(req.getContextPath() + // "/images"); // renderContext.setImageDirectory(sc.getRealPath("/images")); // logger.log(Level.FINE, "image directory " + // sc.getRealPath("/images")); // HashMap contextMap = new HashMap(); // contextMap.put(EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, // renderContext); // htmlOptions.setImageDirectory("output/image"); // htmlOptions.setMasterPageContent(true); // htmlOptions.setPageFooterFloatFlag(true);
ByteArrayOutputStream ostream = new ByteArrayOutputStream(); htmlOptions.setOutputStream(ostream); htmlOptions.setHtmlPagination(true);// 加入分页条 htmlOptions.setEmbeddable(true);// 去除html、head、body标记
IRunAndRenderTask task = birtReportEngine .createRunAndRenderTask(design); if (parameters != null && !parameters.isEmpty()) { task.setParameterValues(parameters); task.validateParameters(); }
String maxRow = req.getParameter("MaxRowsPerQuery"); if (maxRow != null && maxRow.length() > 0) { task.setMaxRowsPerQuery(Integer.parseInt(maxRow));// 设置每次查询最大行数 }
task.setRenderOption(htmlOptions); task.run(); task.close();
ServletOutputStream out = resp.getOutputStream(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<html>"); out.println(" <head>"); out.println(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"); out.println(" <style type=text/css>"); // out.println(" td{border:1px solid #9EBFE0;font-Size:12px;}"); // out.println(" th{background-color:#C3D5ED;border:1px solid #9EBFE0;font-Size:12px;font-weight:bold;text-align:center;}"); out.println(" img { vertical-align:middle;}"); out.println(" </style>"); out.println(" </head>"); out.println(" <body>");
// String ostr = ostream.toString("ISO-8859-1"); String ostr = ostream.toString("utf-8"); if (ostr.length() > 1048576) {// 大于1M则分好页再传到浏览器端,减少网络流量,减轻浏览器压力
ArrayList<Integer> indexArray = new ArrayList<Integer>(); for (int i = 0; ostr.indexOf("page separator", i) != -1;) { int index = ostr.indexOf("page separator", i); indexArray.add(index); i = index + 1; } int totalPage = indexArray.size() + 1; int curPage = 1; if (totalPage > 1) { String strCurPage = req.getParameter("PB_PAGE"); if (strCurPage != null && strCurPage.length() > 0) { curPage = Integer.parseInt(strCurPage); } if (curPage <= 1) { curPage = 1; int index = indexArray.get(curPage - 1); int subIndex = ostr.lastIndexOf("<", index); ostr = ostr.substring(0, subIndex); } else if (curPage >= totalPage) { curPage = totalPage; int index = indexArray.get(curPage - 2); int subIndex = ostr.indexOf(">", index) + 1; ostr = ostr.substring(subIndex); } else { int beginIndex = indexArray.get(curPage - 2); int bgSubIndex = ostr.indexOf(">", beginIndex) + 1; int endIndex = indexArray.get(curPage - 1); int enSubIndex = ostr.lastIndexOf("<", endIndex); ostr = ostr.substring(bgSubIndex, enSubIndex); } }
out.println("<div style= 'width:100%;overflow:auto '>"); out.println(ostr); out.println("</div>"); out.println("<table width='100%' height='32' border='1' align='left' cellpadding='0' cellspacing='0'>"); out.println(" <tr valign='middle' style='background-color:#C3D5ED;'>"); out.println(" <td width='10' style='border-width:0px'> </td>"); out.println(" <td id='btnFirst' width='20' style='border-width:0px'>"); if (curPage > 1) { out.println(" <a href='" + baseUrl + "&PB_PAGE=1'><img src='" + imgBaseUrl + "/icon_page_frist.gif' border='0'></a>"); } else { out.println(" <img src='" + imgBaseUrl + "/icon_page_frist1.gif' border='0'>"); } out.println("</td>"); out.println(" <td id='btnPrev' width='20' style='border-width:0px'>"); if (curPage > 1) { out.println(" <a href='" + baseUrl + "&PB_PAGE=" + (curPage - 1) + "'><img src='" + imgBaseUrl + "/icon_page_prev.gif' border='0'></a>"); } else { out.println(" <img src='" + imgBaseUrl + "/icon_page_prev1.gif' border='0'>"); } out.println("</td>"); out.println(" <td width='150' style='border-width:0px;font-Size:12px;'>"); // out.println(new // String("第".getBytes("utf-8"),"ISO-8859-1") out.println("第" // +"<input id='curPage' type='text' style='width:35px;height:18px;' value='"+curPage+"' readOnly>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")+" "); + "<input id='curPage' type='text' style='width:35px;height:18px;' value='" + curPage + "' readOnly>" + "页" + " "); // out.println(new // String("共".getBytes("utf-8"),"ISO-8859-1") out.println("共" // +"<input id='totalPage' type='text' style='width:35px;height:18px;' value='"+totalPage+"' readOnly>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")); + "<input id='totalPage' type='text' style='width:35px;height:18px;' value='" + totalPage + "' readOnly>" + "页"); out.println(" </td>"); out.println(" <td id='btnNext' width='20' style='border-width:0px'>"); if (curPage < totalPage) { out.println(" <a href='" + baseUrl + "&PB_PAGE=" + (curPage + 1) + "'><img src='" + imgBaseUrl + "/icon_page_next.gif' border='0'></a>"); } else { out.println(" <img src='" + imgBaseUrl + "/icon_page_next1.gif' border='0'>"); } out.println("</td>"); out.println(" <td id='btnLast' width='30' style='border-width:0px'>"); if (curPage < totalPage) { out.println(" <a href='" + baseUrl + "&PB_PAGE=" + totalPage + "'><img src='" + imgBaseUrl + "/icon_page_last.gif' border='0'></a>"); } else { out.println(" <img src='" + imgBaseUrl + "/icon_page_last1.gif' border='0'>"); } out.println("</td>"); out.println(" <td width='140' style='border-width:0px;font-Size:12px;'>"); // out.println(new // String("转到第".getBytes("utf-8"),"ISO-8859-1") out.println("转到第" // +"<input id='gotoPage' type='text' style='width:35px;height:18px;' value=''>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")); + "<input id='gotoPage' type='text' style='width:35px;height:18px;' value=''>" + "页"); out.println(" <img src='" + imgBaseUrl + "/application_go.png' onclick='javascript:gotoPage()'/></td>"); out.println(" <td width='30' style='border-width:0px'><img src='" + imgBaseUrl + "/print.gif' style='cursor:pointer' onclick='window.print()'/></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=pdf' target='_blank'><img border='0' src='" + imgBaseUrl + "/pdf.gif'/></a></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=xls' target='_blank'><img border='0' src='" + imgBaseUrl + "/xls.gif'/></a></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=doc' target='_blank'><img border='0' src='" + imgBaseUrl + "/doc.gif'/></a></td>"); out.println(" <td style='border-width:0px'> </td>"); out.println(" </tr>"); out.println("</table>"); out.println("<script type=\"text/javascript\">"); out.println(" String.prototype.trim=function(){"); out.println(" return this.replace(/(^\\s*)|(\\s*$)/g,'');"); out.println(" }"); out.println(" function gotoPage(){"); out.println(" var spage = document.getElementById('gotoPage').value.trim();"); out.println(" if(spage=='' || spage.indexOf('.')!=-1 || isNaN(spage)) {"); // out.println(" alert('"+new // String("请输入整数".getBytes("utf-8"),"ISO-8859-1")+"');"); out.println(" alert('" + "请输入整数" + "');"); out.println(" return;"); out.println(" }"); out.println(" var ipage = parseInt(spage);"); out.println(" window.location.href = \"" + baseUrl + "&PB_PAGE=\"+ipage;"); out.println(" }"); out.println("</script> "); } else { // 在浏览器端用js实现分页,提高访问速度,减轻对服务器的压力
out.println("<div style= 'width:100%;overflow:auto '>"); out.println(ostr); out.println("</div>"); out.println("<table width='100%' height='32' border='1' align='left' cellpadding='0' cellspacing='0'>"); out.println(" <tr valign='middle' style='background-color:#C3D5ED;'>"); out.println(" <td width='10' style='border-width:0px'> </td>"); out.println(" <td id='btnFirst' width='20' style='border-width:0px'><img src='" + imgBaseUrl + "/icon_page_frist1.gif'/></td>"); out.println(" <td id='btnPrev' width='20' style='border-width:0px'><img src='" + imgBaseUrl + "/icon_page_prev1.gif'/></td>"); out.println(" <td width='150' style='border-width:0px;font-Size:12px;'>"); // out.println(new // String("第".getBytes("utf-8"),"ISO-8859-1")+"<input id='curPage' type='text' style='width:35px;height:18px;' readOnly>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")+" "); out.println("第" + "<input id='curPage' type='text' style='width:35px;height:18px;' readOnly>" + "页" + " "); // out.println(new // String("共".getBytes("utf-8"),"ISO-8859-1")+"<input id='totalPage' type='text' style='width:35px;height:18px;' readOnly>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")); out.println("共" + "<input id='totalPage' type='text' style='width:35px;height:18px;' readOnly>" + "页"); out.println(" </td>"); out.println(" <td id='btnNext' width='20' style='border-width:0px'><img src='" + imgBaseUrl + "/icon_page_next1.gif'/></td>"); out.println(" <td id='btnLast' width='30' style='border-width:0px'><img src='" + imgBaseUrl + "/icon_page_last1.gif'/></td>"); out.println(" <td width='140' style='border-width:0px;font-Size:12px;'>"); // out.println(new // String("转到第".getBytes("utf-8"),"ISO-8859-1")+"<input id='gotoPage' type='text' style='width:35px;height:18px;' value=''>"+new // String("页".getBytes("utf-8"),"ISO-8859-1")); out.println("转到第" + "<input id='gotoPage' type='text' style='width:35px;height:18px;' value=''>" + "页"); out.println(" <img src='" + imgBaseUrl + "/application_go.png' onclick='javascript:gotoPage()'/></td>"); out.println(" <td width='30' style='border-width:0px'><img src='" + imgBaseUrl + "/print.gif' style='cursor:pointer' onclick='window.print()'/></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=pdf' target='_blank'><img border='0' src='" + imgBaseUrl + "/pdf.gif'/></a></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=xls' target='_blank'><img border='0' src='" + imgBaseUrl + "/xls.gif'/></a></td>"); out.println(" <td width='30' style='border-width:0px'><a href='" + baseUrl + "&O_FORMAT=doc' target='_blank'><img border='0' src='" + imgBaseUrl + "/doc.gif'/></a></td>"); out.println(" <td style='border-width:0px'> </td>"); out.println(" </tr>"); out.println("</table>"); out.println("<script type=\"text/javascript\">"); out.println(" var pageArray = [];"); out.println(" var div_list = document.getElementsByTagName('div');"); out.println(" for(var i=0; i<div_list.length; i++){ "); out.println(" if(div_list[i].innerHTML=='page separator') {"); out.println(" div_list[i].style.display='none';"); out.println(" if(pageArray.length==0){"); out.println(" pageArray[0] = div_list[i].previousSibling;"); out.println(" }"); out.println(" pageArray[pageArray.length] = div_list[i].nextSibling;"); out.println(" }"); out.println(" }"); out.println(" function displayPage(ipage){"); out.println(" if(pageArray.length==1){"); out.println(" ipage = 1;"); out.println(" document.getElementById('btnFirst').innerHTML= \"<img src='" + imgBaseUrl + "/icon_page_frist1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnPrev').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_prev1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnNext').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_next1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnLast').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_last1.gif' style='cursor:default'/>\";"); out.println(" }else{"); out.println(" if(ipage<=1){"); out.println(" ipage = 1;"); out.println(" document.getElementById('btnFirst').innerHTML= \"<img src='" + imgBaseUrl + "/icon_page_frist1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnPrev').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_prev1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnNext').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_next.gif' style='cursor:pointer' onclick='javascript:nextPage()'/>\";"); out.println(" document.getElementById('btnLast').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_last.gif' style='cursor:pointer' onclick='javascript:lastPage()'/>\";"); out.println(" }else if(ipage>=pageArray.length){"); out.println(" ipage = pageArray.length;"); out.println(" document.getElementById('btnFirst').innerHTML= \"<img src='" + imgBaseUrl + "/icon_page_frist.gif' style='cursor:pointer' onclick='javascript:firstPage()'/>\";"); out.println(" document.getElementById('btnPrev').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_prev.gif' style='cursor:pointer' onclick='javascript:prevPage()'/>\";"); out.println(" document.getElementById('btnNext').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_next1.gif' style='cursor:default'/>\";"); out.println(" document.getElementById('btnLast').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_last1.gif' style='cursor:default'/>\";"); out.println(" }else{"); out.println(" document.getElementById('btnFirst').innerHTML= \"<img src='" + imgBaseUrl + "/icon_page_frist.gif' style='cursor:pointer' onclick='javascript:firstPage()'/>\";"); out.println(" document.getElementById('btnPrev').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_prev.gif' style='cursor:pointer' onclick='javascript:prevPage()'/>\";"); out.println(" document.getElementById('btnNext').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_next.gif' style='cursor:pointer' onclick='javascript:nextPage()'/>\";"); out.println(" document.getElementById('btnLast').innerHTML = \"<img src='" + imgBaseUrl + "/icon_page_last.gif' style='cursor:pointer' onclick='javascript:lastPage()'/>\";"); out.println(" }"); out.println(" }"); out.println(" for(var i=0; i<pageArray.length;i++){"); out.println(" if(i==(ipage-1)){"); out.println(" pageArray[i].style.display='inline';"); out.println(" }else{"); out.println(" pageArray[i].style.display='none';"); out.println(" }"); out.println(" }"); out.println(" document.getElementById('curPage').value = ipage;"); out.println(" }"); out.println(" function firstPage(){"); out.println(" displayPage(1);"); out.println(" }"); out.println(" function prevPage(){"); out.println(" var spage = document.getElementById('curPage').value;"); out.println(" var ipage = parseInt(spage)-1;"); out.println(" displayPage(ipage);"); out.println(" }"); out.println(" function nextPage(){"); out.println(" var spage = document.getElementById('curPage').value;"); out.println(" var ipage = parseInt(spage)+1;"); out.println(" displayPage(ipage);"); out.println(" }"); out.println(" function lastPage(){"); out.println(" displayPage(pageArray.length);"); out.println(" }"); out.println(" String.prototype.trim=function(){"); out.println(" return this.replace(/(^\\s*)|(\\s*$)/g,'');"); out.println(" }"); out.println(" function gotoPage(){"); out.println(" var spage = document.getElementById('gotoPage').value.trim();"); out.println(" if(spage=='' || spage.indexOf('.')!=-1 || isNaN(spage)) {"); // out.println(" alert('"+new // String("请输入整数".getBytes("utf-8"),"ISO-8859-1")+"');"); out.println(" alert('" + "请输入整数" + "');"); out.println(" return;"); out.println(" }"); out.println(" var ipage = parseInt(spage);"); out.println(" displayPage(ipage);"); out.println(" }"); out.println(" document.getElementById('totalPage').value=pageArray.length;"); out.println(" firstPage();"); out.println("</script> "); } out.println("</body>"); out.println("</html>"); out.flush();
out.close(); ostream.close();
} else {// 导出文件
RenderOption options;
if (outFormat.equals("pdf")) { resp.setContentType("application/pdf"); resp.setHeader("Content-Disposition", "attachment; filename=export.pdf"); options = new PDFRenderOption(); options.setOutputFormat(RenderOption.OUTPUT_FORMAT_PDF); } else { if (outFormat.equals("xls")) { resp.setContentType("application/msexcel"); resp.setHeader("Content-disposition", "attachment; filename=export.xls"); } else if (outFormat.equals("doc")) { resp.setContentType("application/msword"); resp.setHeader("Content-disposition", "attachment; filename=export.doc"); } else { resp.setContentType("text/html"); } options = new HTMLRenderOption(); options.setOutputFormat(RenderOption.OUTPUT_FORMAT_HTML); } options.setOutputStream(resp.getOutputStream());
IRunAndRenderTask task = birtReportEngine .createRunAndRenderTask(design);// 不生成document文件 if (parameters != null && !parameters.isEmpty()) { task.setParameterValues(parameters);// 设置报表参数 task.validateParameters(); } task.setRenderOption(options); task.run(); task.close();}
} catch (Exception e) { e.printStackTrace(); throw new ServletException(e);}}
/** * The doPost method of the servlet. * */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response); }
/** * Initialization of the servlet. * * @throws ServletException * if an error occure */ public void init() throws ServletException { BirtEngine.initBirtConfig();
}
}
这个servlet其实很简单,就是调用自定义的report engine往客户端输出了HTML格式的报表render显示,还在网客户端打印了一些资源,其中包含一些用于导航的图表文件,放置在report/reports/images下
WEB-INF下面的文件如下:
其中classes放置定制的BirtEngine和ReportServlet,lib用于放置runtime ReportEngine类库,web.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"><web-app id="WebApp"><servlet><servlet-name>WebReport</servlet-name><servlet-class>birtbird.ReportServlet</servlet-class></servlet><servlet-mapping><servlet-name>WebReport</servlet-name><url-pattern>/webReport</url-pattern></servlet-mapping></web-app>
这样我们可以访问/report/webReport?ReportName=customerOrders.rptdesign&customerno=114来访问customer.rptdesign,也可以用如下的方式:
<%@ page contentType="text/html;charset=GBK" %><%@ page import = "javax.servlet.http.*" %><%@ include file="/includes/jsp/init.jsp"%><% String report_url = "/report/webReport?ReportName=customerOrders.rptdesign&customerno=114";%><script language="javascript">location.href="<%=report_url%>";</script>
源码中我们把报表的访问路径设置成了report/reports下,
customerOrders.rptdesign报表的设计如下:
其中包含参数customerno,默认值是114
在自定义的报表查看器中预览如下(注意导航栏和工具栏在一起,都在下面):
翻到第4页
导出的excel:
导出的word:
实际上我们还能利用报表展示器的扩展点开发一个自定义的eclipse插件类型的报表展示器,这种方式能直接调用BIRT已经封装好的viewer
plugin.xml的内容如下:
<?xml version="1.0" encoding="UTF-8"?><?eclipse version="3.2"?><plugin> <extension id="application" point="org.eclipse.core.runtime.applications"> <application> <run class="org.eclipse.birt.examples.rcpviewer.Application"> </run> </application> </extension> <extension point="org.eclipse.ui.perspectives"> <perspective name="Perspective" class="org.eclipse.birt.examples.rcpviewer.Perspective" id="org.eclipse.birt.examples.rcpviewer.perspective"> </perspective> </extension> <extension point="org.eclipse.ui.views"> <view name="View" class="org.eclipse.birt.examples.rcpviewer.View" id="org.eclipse.birt.examples.rcpviewer.view"> </view> </extension> <extension point="org.eclipse.birt.report.viewer.appcontext"> <appcontext class="org.eclipse.birt.examples.rcpviewer.MyAppContext"> </appcontext> </extension></plugin>
RCP客户端程序最终运行效果如下:
至于如何扩展BIRT报表的API,第十四章会详细描述。