第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

第十三章 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下

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

WEB-INF下面的文件如下:

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

其中classes放置定制的BirtEngineReportServlet,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下,

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

customerOrders.rptdesign报表的设计如下:

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

其中包含参数customerno,默认值是114

在自定义的报表查看器中预览如下(注意导航栏和工具栏在一起,都在下面):

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

翻到第4

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

导出的excel

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

导出的word

第十三章 BIRT表格引擎API及报表API (续)-自定义web BIRT展示器

实际上我们还能利用报表展示器的扩展点开发一个自定义的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及报表API (续)-自定义web BIRT展示器
至于如何扩展BIRT报表的API,第十四章会详细描述。