B/S环境下使用JFreeReport展示报表
肖菁
软件工程师
king@vivianj.org
BEA dev2dev长沙UserGroup Leader,开源项目BuildFileDesigner、V-SuperMedia创始人,IBM developerWorks/BEA dev2dev/Sun技术社区撰稿人,主要研究J2EE编程技术、Web Service技术以及他们在 WebSphere、WebLogic、 Apache平台上的实现,拥有 IBM 的 Developing With Websphere Studio证书。
[文章摘要] 本文主要讲述如何在B/S环境下使用JFreeReport来展示报表,表现形式包括HTML表格、PDF文件、PNG图片、XSL文件等。
[关键词]: JFreeReport 报表
1 谁需要阅读这篇文章
本文的读者是已经可以熟练使用JFreeReport生成报表内容、能够在GUI范围内展示报表但还不是很清楚如何在Web环境下展示出来的用户。如果你还不是很熟悉这方面的内容请阅读作者的上一篇文章《使用JFreeReport生成报表》。
2 基础知识
在作者的上一篇文章发表后,很多读者发来E_Mail询问如何在Web环境下使用JFreeReport来展示报表内容,作者经过研究后有了一些心得,因此记录了下来和大家共享。下面就开始一些准备工作。
2.1 JFreeReport目前支持的展示格式
JFreeReport目前支持的展示格式包括HTML表格形式、PDF文件、XSL文件、PNG文件,你还可以扩展JFreeReport来生成自己需要的展示形式。
2.2 展示原理
JFreeReport的展示原理是比较简单的:采用Servlet作为载体,根据已经定义好的JFreeReport报表内容,转化为对应的HTML源代码、PDF文件、XSL文件或者PNG文件,发送给浏览器用于展示。
3 准备工作
3.1 Web容器准备
请下载一个支持Servlet的Web容器,作者这里采用的是Tomcat,版本是5.5.8
3.2 Web应用配置
在Tomcat下面新增加一个Web应用(作者配置该Web应用的上下文路径为/jfr),然后将JFreeReport需要的支持jar文件放在该Web应用的lib目录下,主要是解压缩JFreeReport下载文件目录下的jfreereport-xxx-all.jar(xxx是下载的JFreeReport版本号)和lib目录下的所有jar文件。
4 开始工作
接下来就开始介绍如何使用JFreeReport来展示报表内容了,作者首先采用其中HelloWorld类定义的简单报表来演示如何分别用HTML表格、PDF文件、XSL文件和PNG图片来展示报表内容,最后给出了一个用HTML表格来展示复杂报表内容的例子。
4.1 准备报表内容
/*
* 2004-9-28 肖菁 创建
*/
package com.jandar.egov;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.Point2D;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import org.jfree.report.Boot;
import org.jfree.report.ElementAlignment;
import org.jfree.report.JFreeReport;
import org.jfree.report.PageHeader;
import org.jfree.report.ReportProcessingException;
import org.jfree.report.ShapeElement;
import org.jfree.report.elementfactory.LabelElementFactory;
import org.jfree.report.elementfactory.StaticShapeElementFactory;
import org.jfree.report.elementfactory.TextFieldElementFactory;
import org.jfree.report.modules.gui.base.PreviewDialog;
import org.jfree.report.util.Log;
import org.jfree.ui.FloatDimension;
/**
* 使用JFreeReport生成报表的简单例子,用于演示使用JFreeReport生成报表的一些基本步骤
*
* 本例子中,为了简化操作,报表定义是使用java直接编码
*
*/
public class HelloWorld {
public HelloWorld(){}
/**
* 创建生成报表需要用到的数据
*
* @返回一个TableModel实例
*/
public TableModel getTableModel(){
Object[] columes = new String[]{"id","name"};
TableModel tableModel = new DefaultTableModel(columes,100);
//生成100条记录
for(int i = 0; i<100 ; i++){
tableModel.setValueAt("100" + i,i,0);
tableModel.setValueAt("中文" + i,i,1);
}
return tableModel;
}
/**
* 创建一个报表定义,定义报表的列信息
*
* @返回一个报表定义实例
*/
public JFreeReport getReportDefinition(){
JFreeReport jFreeReport = new JFreeReport();
jFreeReport.setName("中文测试");
//定义报表的第一列
TextFieldElementFactory colume1 = new TextFieldElementFactory();
colume1.setName("id");
//定义列的起始位置
colume1.setAbsolutePosition(new Point2D.Float(0, 0));
//定义列的范围
colume1.setMinimumSize(new FloatDimension(150, 20));
//定义显示TableModel中的哪一列数据
colume1.setFieldname("id");
jFreeReport.getItemBand().addElement(colume1.createElement());
TextFieldElementFactory colume2 = new TextFieldElementFactory();
colume2.setName("name");
colume2.setAbsolutePosition(new Point2D.Float(200, 0));
colume2.setMinimumSize(new FloatDimension(150, 20));
colume2.setFieldname("name");
jFreeReport.getItemBand().addElement(colume2.createElement());
return jFreeReport;
}
/**
* 创建一个表头定义,定义报表的表头信息
*
* @返回一个报表表头实例
*/
public PageHeader getPageHeader(){
PageHeader pageHeader = new PageHeader();
//定义将表头处画填充过的框
ShapeElement shape =StaticShapeElementFactory.createRectangleShapeElement("id",
new Color(204,204,204),
null,
new Rectangle(0, 0, -100, 20),
false,
true);
pageHeader.addElement(shape);
//定义将表头第一列
LabelElementFactory colume1 = new LabelElementFactory();
colume1.setName("id");
colume1.setAbsolutePosition(new Point2D.Float(0, 10));
colume1.setMinimumSize(new FloatDimension(150, 20));
//设置列的对齐方式
colume1.setHorizontalAlignment(ElementAlignment.CENTER);
//设置列中显示的文字
colume1.setText("Id");
pageHeader.addElement(colume1.createElement());
LabelElementFactory colume2 = new LabelElementFactory();colume2.setName("name");
colume2.setAbsolutePosition(new Point2D.Float(200, 10));
colume2.setMinimumSize(new FloatDimension(150, 20));
colume2.setText("Name");
colume2.setHorizontalAlignment(ElementAlignment.CENTER);
pageHeader.addElement(colume2.createElement());
return pageHeader;
}
/**
* 创建一个完整的报表定义
*
* @返回一个报表定义的实例
*/
public JFreeReport getReport(){
TableModel data = getTableModel();
JFreeReport report = getReportDefinition();
PageHeader pageHeader = getPageHeader();
report.setPageHeader(pageHeader);
report.setData(data);
return report;
}
}
4.2 简单报表的展示
4.2.1 简单报表的HTML展示
JFreeReport提供HtmlProcessor类来将输入的JFreeReport报表变成HTML表格形式,最后通过Servlet的输出通道展示给用户,具体的用法如下例:
/*
* 2004-9-28 肖菁 创建
*/
package com.jandar.egov;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jfree.report.JFreeReport;
import org.jfree.report.modules.output.table.base.TableProcessor;
import org.jfree.report.modules.output.table.html.HtmlProcessor;
import org.jfree.report.modules.output.table.html.StreamHtmlFilesystem;
import org.jfree.report.util.Log;
/**
* HtmlExampleServlet演示如何通过HTML表格在Web环境下展示JFreeReport定义的表格
*/
public class HtmlExampleServlet extends HttpServlet
{
public void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException
{
doPost(request, response);
}
public void doPost(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException
{
TableProcessor worker;
//设置输出页面的Meta信息
response.setHeader("Content-Disposition", "inline; filename=\"" + "unknown.html" + "\"");
//设置页面的输出格式
response.setHeader("Content-Type", "text/html");
try
{
//获取Servlet的输出流
OutputStream out = response.getOutputStream();
//获取HelloWorld中定义的报表
HelloWorld helloWorld = new HelloWorld();
JFreeReport report = helloWorld.getReport();
//将报表和Servlet的输出流作为参数传递给TableProcessor的实例
final HtmlProcessor processor = new HtmlProcessor(report);
processor.setFilesystem(new StreamHtmlFilesystem(out));
worker = processor;
}
catch (Exception e)
{
Log.debug("无法解析报表定义", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
try
{
//输出结果
worker.processReport();
}
catch (Exception e)
{
Log.debug("输出结果产生错误", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
}
}
[注] 这里需要提醒大家的是Web下面的JFreeReport展示内容并不具备和GUI界面下同样的分页能力,也就是说不管你的报表内容有多少,他们都会在一页中显示。
4.2.2 报表的XSL文件展示
XSL展示的方法和HTML的基本类似,只是采用ExcelProcessor作为处理类,然后将输出文件格式修改为"application/vnd.ms-excel",具体的代码调用如下(注意粗体显示的地方):
/*
* TableProcessor是处理HTML输出的类
* 他将提供的JFreeReport报表定义转化为HTML表格内容,然后通过Servlet的输出流展示给用户
*/
TableProcessor worker;
//设置输出页面的Meta信息
response.setHeader(
"Content-Disposition",
"inline; filename=\"" + "unknown.xls" + "\"");
//设置页面的输出格式
response.setHeader("Content-Type", "application/vnd.ms-excel");
try {
//获取Servlet的输出流
OutputStream out = response.getOutputStream();
//获取HelloWorld中定义的报表
HelloWorld helloWorld = new HelloWorld();
JFreeReport report = helloWorld.getReport();
//将报表和Servlet的输出流作为参数传递给TableProcessor的实例
final ExcelProcessor processor = new ExcelProcessor(report);
processor.setOutputStream(out);
worker = processor;
} catch (Exception e) {
Log.debug("无法解析报表定义", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
try {
//输出结果
worker.processReport();
} catch (Exception e) {
Log.debug("输出结果产生错误", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
4.2.3 报表的PNG图片展示
报表的PNG图片展示和上面的处理有些不同,他是先将报表内容存入BufferedImage对象中缓存起来,然后通过Servlet的输出通道传输给用户的,所以处理过程比其他几个复杂一些,具体的调用代码如下:
//定义缓存图片的对象
BufferedImage image = null;
//获取当前需要显示的页数
String param = request.getParameter("page");
if (param == null) {
Log.debug("Page attribute is missing");
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
int page = 0;
try {
page = Integer.parseInt(param);
} catch (Exception e) {
Log.debug("The page-parameter is invalid", e);
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
PageableReportProcessor worker;
//设置输出页面的Meta信息
response.setHeader(
"Content-Disposition",
"inline;filename=\"report-page-" + page + ".png\"");
//设置页面的输出格式
response.setHeader("Content-Type", "image/png");
// 获取HelloWorld中定义的报表
HelloWorld helloWorld = new HelloWorld();
JFreeReport report = helloWorld.getReport();
try {
// 初始化输出对象
worker = new PageableReportProcessor(report);
//获取页面格式
final PageFormat pageFormat =
worker.getReport().getDefaultPageFormat();
//创建被缓存的报表内容
image = Util.createImage(pageFormat);
final Graphics2D g2 = image.createGraphics();
g2.setPaint(Color.white);
g2.fillRect(
0,
0,
(int) pageFormat.getWidth(),
(int) pageFormat.getHeight());
//将报表内容输出到缓存中
final G2OutputTarget target = new G2OutputTarget(g2, pageFormat);
target.open();
worker.setOutputTarget(target);
ReportStateList pageStateList = worker.repaginate();
ReportState state = pageStateList.get(page);
worker.processPage(state, target);
target.close();
//获取Servlet的输出流
final ServletOutputStream out = response.getOutputStream();
// 输出图片
final PngEncoder encoder = new PngEncoder(image, true, 0, 9);
final byte[] data = encoder.pngEncode();
out.write(data);
out.flush();
} catch (Exception e) {
Log.debug("无法解析报表定义", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
联系客服