您的位置:首页 > 编程语言 > ASP

JasperReport报表设计总结(一)

2010-10-06 13:31 399 查看
共三篇,下接:http://jimmy-shine.javaeye.com/blog/123595

为了开发报表,已经拜读了一大堆的资料,其中大部分是重复的。可以看得出,国人还是比较热衷于copy&paste的工作。所以找了一大堆的资料都是相同的,或者可以用一个词来形容,换汤不换药的。

有必要对于jasper Report的学习进度进行一下总结,一来可以更新一下以前的资料中的一些旧得不能再旧的不再适用的东西,二来让后来者可以轻松的上手。

首先,jasperReport是一个以java实现的报表工具,(好像是句废话)。可以实现多种格式的报表。

再我们先理解一下jasperReport的实现过程。笔者不再画图,网上到处都是。

1)定制报表格式。

有二种方式,一种就是写jrxml文件,其实就是xml文件,只不过是后缀名不一样罢了。另一种方式更直接,就是生成一个JasperDesign类的实
例,在japsperDesign中自己定义模板。jrxml文件也是通过一个JRXmlLoad加载过来,转成JasperDesign类的实例。也就
是说写jrxml文件还需要进行解析,加载。现实中我们使用的报表一般格式比较固定,因而可以通过先使用iReport工具生成模板,再加载解析的方式。
这种方式简单,而且可见性强。

2)填充数据。

在最新版(2007.4.30发布)的jasperReports1.3.3中,支持了很多的格式,包括了对于Hibernate的支持。填充数据对于我
们经常使用的来说,一般是二种方式,一种方式是通过JDBC连接提供数据源,一种就是通过javaBean的集合提供数据源。当然还有web
Service的xml文件提供的。我的建议是,如果你的程序中的统计直接使用Jdbc就可以完成,那么就使用jdbc数据源的方法,反之,使用
javaBean的集合是不错的选择,因为这样不会在意你的数据的来源,你也可以任意处理,比如说,要通过权限检查的数据才在报表中生成的话,就可以过滤
到不符合权限的数据。

3)显示或打印。

显示,即将JasperReport生成的文件直接显示出来,打印所使用的方式其实就是生成文件,然后调用打印来对文件进行打印。

看起来是不是很简单,对,确实很简单。

笔者主要从事基于B/S模式的开发,相信大部分人的使用也是基于web进行使用。故笔者对于基于web的开发进行详细讲述。

1、工程环境配置。

将以下包加入WEB-INF/lib中。

commons-beanutils-1.7.jar;commons-collections-2.1.jar;commons-digester-1.7.jar;commons-logging-1.0.2.jar;commons-logging-api-1.0.2.jar;itext-1.3.1.jar;jasperreports-1.3.3.jar;jdt-compiler-3.1.1.jar;jxl-2.6.jar;png-encoder-1.5.jar;poi-2.0-final-20040126.jar

 以上包是jasperReport必须。

2、iReport的安装

这个很简单,直接下一步就可以了。

3、使用iReport生成 .jasper文件

.jasper是经过编译的japserReport模板,即.jrxml编译后的。

对于iReport的使用网络上已经有了详细的中文的文档,具体可以下载附件查看。使用.jasper文件可以避免在系统中再进行编译,增加系统的压力。

4、数据填充

数据填充是相对于比较重要的一步,数据填充的目的是为了将数据填充进去,生成一个JapserPrint对象。笔者在之前已经阐述过,现在主要是基于关系
型数据库(比较简单的,没有权限控制的),以及基于JavaBean
Collection进行数据填充。进行数据填充的基本就是一定要实现JRDataSource,JRDataSource定义了二个方法,一个是指针移
动的方法next(),另一个是取值的getFieldValue()方法,用来取值填充。

对于关系型数据库,即直接利用数据库的表来生成报表的,只需要传入一个Java
Connection即可。JasperReport已经有了个默认的实现的JRDataSource的接口了。对于Java
Conncetion的获得,笔者建议使用工厂方法或者使用Spring方式来获得。可以参照笔者写的如下:

java 代码

/**

* @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.

* @author Jimmy.Shine 2007-5-11

*/

package
cn.com.reachway.framework.report;

import
java.sql.Connection;

import
java.sql.DriverManager;

import
cn.com.reachway.framework.exception.JasperReportException;

/**

* Used for get a JDBC connection for Jasper Report

*/

public

class
JDBCConnection {

/**

* Which Jdbc driver were used. Like: "net.sourceforge.jtds.jdbc.Driver"

*/

private
String jdbcDriver;

/**

* The jdbc url,define which database server,which db. Like:

* "jdbc:jtds:sqlserver://192.168.1.50:1433;DatabaseName=JAVA5;SelectMethod=Cursor"

*/

private
String jdbcUrl;

private
String dbUser;

private
String dbPassword;

public
String getDbPassword() {

return
dbPassword;

}

public

void
setDbPassword(String dbPassword) {

this
.dbPassword = dbPassword;

}

public
String getDbUser() {

return
dbUser;

}

public

void
setDbUser(String dbUser) {

this
.dbUser = dbUser;

}

public
String getJdbcDriver() {

return
jdbcDriver;

}

public

void
setJdbcDriver(String jdbcDriver) {

this
.jdbcDriver = jdbcDriver;

}

public
String getJdbcUrl() {

return
jdbcUrl;

}

public

void
setJdbcUrl(String jdbcUrl) {

this
.jdbcUrl = jdbcUrl;

}

public
JDBCConnection() {

super
();

}

/**

* Get the Connection

* @return connection

* @throws JasperReportException

*/

public
Connection getConnection()
throws
JasperReportException {

Connection con;

try
{

check();

Class.forName(
this
.jdbcDriver);

con = DriverManager.getConnection(
this
.jdbcUrl,
this
.dbUser,
this
.dbPassword);

return
con;

}
catch
(Exception e) {

e.printStackTrace();

throw

new
JasperReportException(
"Get JDBC Connection Error"
);

}

}

/**

* Check the Configure

* @throws JasperReportException

*/

private

void
check()
throws
JasperReportException {

if
(
this
.jdbcDriver ==
null
||
this
.jdbcDriver.equals(
""
) ||
this
.jdbcUrl ==
null
||
this
.jdbcUrl.equals(
""
)

||
this
.dbUser ==
null
||
this
.dbUser.equals(
""
) ||
this
.dbPassword ==
null
) {

throw

new
JasperReportException(
"Jdbc Configure error!"
);

}

}

}

java 代码

/**

* @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.

* @author Jimmy.Shine 2007-5-14

*/

package
cn.com.reachway.framework.report.dataSource;

import
net.sf.jasperreports.engine.JRDataSource;

import
net.sf.jasperreports.engine.JRException;

import
net.sf.jasperreports.engine.JRField;

/**

* 报表的dataSource的基类,所有利用DataSource产生报表的继承此类

*/

public

abstract

class
ReportDataSource
implements
JRDataSource {

/**

* 取值

*/

public

abstract
Object getFieldValue(JRField jrField)
throws
JRException;

/**

* 指针移动

*/

public

abstract

boolean
next()
throws
JRException;

}

  这样可以共用配置文件中的jdbc连接的相关参数。

对于其它的数据源,JavaBean
Collection,笔者采用了一个抽象类,使用抽象类的目的,是为了使开发者尽可能不用直接接触jasperReport(此为笔者自己的方式,笔者
是PM,为了考虑底下的人的开发)。以下为抽象类以及笔者提供的一个sample:

/**

* @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.

* @author Jimmy.Shine 2007-5-14

*/

package
cn.com.reachway.framework.report.dataSource;

import
java.util.ArrayList;

import
java.util.List;

import
net.sf.jasperreports.engine.JRException;

import
net.sf.jasperreports.engine.JRField;

/**

* 利用JavaBean Collection生成ReportDataSource的例子

*/

public

class
ReportDataSourceSample
extends
ReportDataSource {

private
List docs =
new
ArrayList();

private

int
index = -
1
;

public
ReportDataSourceSample() {

for
(
int
i =
0
; i <
10
; i++) {

Document doc =
new
Document(
"ViewTimes is:"
+ i, i);

this
.docs.add(doc);

}

}

// 内部类,作为demo时使用

private

class
Document {

private
String name;

private

int
viewTimes;

public
String getName() {

return
name;

}

public

void
setName(String name) {

this
.name = name;

}

public

int
getViewTimes() {

return
viewTimes;

}

public

void
setViewTimes(
int
viewTimes) {

this
.viewTimes = viewTimes;

}

public
Document() {

}

public
Document(String name,
int
viewTimes) {

this
.name = name;

this
.viewTimes = viewTimes;

}

}

public
List getDocs() {

return
docs;

}

public

void
setDocs(List docs) {

this
.docs = docs;

}

@Override

public
Object getFieldValue(JRField jrField)
throws
JRException {

String fieldName = jrField.getName();

Document doc =
this
.docs.get(index);

if
(
"name"
.equals(fieldName)) {

return
doc.getName();

}

if
(
"viewTimes"
.equals(fieldName)) {

return
doc.getViewTimes();

}

return

null
;

}

@Override

public

boolean
next()
throws
JRException {

index++;

return
(index <
this
.docs.size());

}

}

java 代码

以上的例子应当很清楚的写明了如何生成数据源。

对于数据源的填充,笔者使用了二个类,分别用来对应使用Connction及JavaBean Collection进行填充。

java 代码

/**

* @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.

* @author Jimmy.Shine 2007-5-12

*/

package
cn.com.reachway.framework.report.jasperPrint;

import
java.io.File;

import
java.sql.Connection;

import
java.util.Map;

import
net.sf.jasperreports.engine.JRException;

import
net.sf.jasperreports.engine.JasperFillManager;

import
net.sf.jasperreports.engine.JasperPrint;

import
net.sf.jasperreports.engine.JasperReport;

import
net.sf.jasperreports.engine.util.JRLoader;

import
cn.com.reachway.framework.exception.JasperReportException;

/**

* 使用报表模板及数据等来生成JapserPrint

*/

public

class
JasperPrintWithConnection {

/** 传入的参数 */

private
Map params;

/** 模板文件的地址 */

private
String reportFilePath;

/** JDBC connection */

private
Connection con;

public
Connection getCon() {

return
con;

}

public

void
setCon(Connection con) {

this
.con = con;

}

public
Map getParams() {

return
params;

}

public

void
setParams(Map params) {

this
.params = params;

}

public
String getReportFilePath() {

return
reportFilePath;

}

public

void
setReportFilePath(String reportFilePath)
throws
JasperReportException {

if
(reportFilePath ==
null
|| !reportFilePath.endsWith(
".jasper"
))

throw

new
JasperReportException(
"您传入的模板文件格式不对,请传入以.jasper为后缀的文件!"
);

this
.reportFilePath = reportFilePath;

}

public
JasperPrintWithConnection() {

super
();

}

public
JasperPrintWithConnection(String reportFilePath, Map params, Connection con)
throws
JasperReportException {

if
(reportFilePath ==
null
|| !reportFilePath.endsWith(
".jasper"
))

throw

new
JasperReportException(
"模板文件格式不对,请传入以.jasper为后缀的文件!"
);

if
(con ==
null
)

throw

new
JasperReportException(
"Conncetion不应当为null!"
);

this
.setReportFilePath(reportFilePath);

this
.setParams(params);

this
.setCon(con);

}

/**

* 取得JasperPrint

* @return

* @throws JasperReportException

*/

public
JasperPrint getJasperPrint()
throws
JasperReportException {

File reportFile =
new
File(
this
.reportFilePath);

if
(!reportFile.exists())

throw

new
JasperReportException(
"传入的模板文件不存在!"
);

try
{

// Load编译好的模板

JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());

// 进行数据填充

JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
this
.params,
this
.con);

return
jasperPrint;

}
catch
(JRException jre) {

jre.printStackTrace();

throw

new
JasperReportException(
"在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!"
);

}

}

}

/**

* @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.

* @author Jimmy.Shine 2007-5-14

*/

package
cn.com.reachway.framework.report.jasperPrint;

import
java.io.File;

import
java.util.Map;

import
net.sf.jasperreports.engine.JRDataSource;

import
net.sf.jasperreports.engine.JRException;

import
net.sf.jasperreports.engine.JasperFillManager;

import
net.sf.jasperreports.engine.JasperPrint;

import
net.sf.jasperreports.engine.JasperReport;

import
net.sf.jasperreports.engine.util.JRLoader;

import
cn.com.reachway.framework.exception.JasperReportException;

/**

*

*/

public

class
JasperPrintWithDataSource {

/** 传入的参数 */

private
Map params;

/** 模板文件的地址 */

private
String reportFilePath;

/** dataSrouce */

private
JRDataSource dataSource;

public
JRDataSource getDataSource() {

return
dataSource;

}

public

void
setDataSource(JRDataSource dataSource) {

this
.dataSource = dataSource;

}

public
Map getParams() {

return
params;

}

public

void
setParams(Map params) {

this
.params = params;

}

public
String getReportFilePath() {

return
reportFilePath;

}

public

void
setReportFilePath(String reportFilePath)
throws
JasperReportException {

if
(reportFilePath ==
null
|| !reportFilePath.endsWith(
".jasper"
))

throw

new
JasperReportException(
"您传入的模板文件格式不对,请传入以.jasper为后缀的文件!"
);

this
.reportFilePath = reportFilePath;

}

public
JasperPrintWithDataSource() {

super
();

}

public
JasperPrintWithDataSource(String reportFilePath, Map params, JRDataSource dataSource)

throws
JasperReportException {

if
(reportFilePath ==
null
|| !reportFilePath.endsWith(
".jasper"
))

throw

new
JasperReportException(
"模板文件格式不对,请传入以.jasper为后缀的文件!"
);

if
(dataSource ==
null
)

throw

new
JasperReportException(
"DataSource不应当为null!"
);

this
.setReportFilePath(reportFilePath);

this
.setParams(params);

this
.setDataSource(dataSource);

}

/**

* 取得JasperPrint

* @return

* @throws JasperReportException

*/

public
JasperPrint getJasperPrint()
throws
JasperReportException {

File reportFile =
new
File(
this
.reportFilePath);

if
(!reportFile.exists())

throw

new
JasperReportException(
"传入的模板文件不存在!"
);

try
{

// Load编译好的模板

JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());

// 进行数据填充

JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
this
.params,
this
.dataSource);

return
jasperPrint;

}
catch
(JRException jre) {

jre.printStackTrace();

throw

new
JasperReportException(
"在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!"
);

}

}

}

java 代码

其中使用的JasperReportException为笔者定义的异常,用来统一处理报表异常。

5、报表产生

报表产生是程序中最终可见的一部分,在jasperReport的demo中,大部分中使用了jasperReport的
net.sf.jasperreports.j2ee.servlets.*中的类来生成。其实这也算是开源的产品的一个问题,其实
jasperReport提供的report的工具,只能算是demo级别的,不能算是产品级别的。相信很多的朋友在使用的时候就碰上无法生成的问题。笔
者在此基础上封装了一下。

具体参见以下:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: