第十三章 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 classpath ClassLoader 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,第十四章会详细描述。