翻译|其它|编辑:郝浩|2007-09-05 11:23:56.000|阅读 1518 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
为了开发报表,已经拜读了一大堆的资料,其中大部分是重复的。可以看得出,国人还是比较热衷于 copy&paste 的工作。所以找了一大堆的资料都是相同的,或者可以用一个词来形容,换汤不换药的。
有必要对于 jasper Report 的学习进度进行一下总结,一来可以更新一下以前的资料中的一些旧得不能再旧的不再适用的东西,二来让后来者可以轻松的上手。
首先,jasperReport 是一个以 java 实现的报表工具,(好像是句废话)。可以实现多种格式的报表。
再我们先理解一下 jasperReport 的实现过程。笔者不再画图,网上到处都是。
1)定制报表格式。
有二种方式,一种就是写 jrxml 文件,其实就是 xml 文件,只不过是后缀名不一样罢了。另一种方式更直接,就是生成一个 JasperDesign 类的实例,在 japsperDesign 中自己定义模板。Jrxml 文件也是通过一个 JRXmlLoad 加载过来,转成 JasperDesign 类的实例。也就是说写 jrxml 文件还需要进行解析,加载。现实中我们使用的报表一般格式比较固定,因而可以通过先使用 iReport 工具生成模板,再加载解析的方式。这种方式简单,而且可见性强。
2)填充数据。
在最新版(2007.4.30发布)的 jasperReports
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-
以上包是 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 代码
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report;
6.
7. import java.sql.Connection;
8. import java.sql.DriverManager;
9.
10. import cn.com.reachway.framework.exception.JasperReportException;
11.
12. /**
13. * Used for get a JDBC connection for Jasper Report
14. */
15. public class JDBCConnection {
16. /**
17. * Which Jdbc driver were used. Like: "net.sourceforge.jtds.jdbc.Driver"
18. */
19. private String jdbcDriver;
20. /**
21. * The jdbc url,define which database server,which db. Like:
22. * "jdbc:jtds:sqlserver://192.168.1.50:1433;DatabaseName=JAVA5;SelectMethod=Cursor"
23. */
24. private String jdbcUrl;
25.
26. private String dbUser;
27.
28. private String dbPassword;
29.
30. public String getDbPassword() {
31. return dbPassword;
32. }
33.
34. public void setDbPassword(String dbPassword) {
35. this.dbPassword = dbPassword;
36. }
37.
38. public String getDbUser() {
39. return dbUser;
40. }
41.
42. public void setDbUser(String dbUser) {
43. this.dbUser = dbUser;
44. }
45.
46. public String getJdbcDriver() {
47. return jdbcDriver;
48. }
49.
50. public void setJdbcDriver(String jdbcDriver) {
51. this.jdbcDriver = jdbcDriver;
52. }
53.
54. public String getJdbcUrl() {
55. return jdbcUrl;
56. }
57.
58. public void setJdbcUrl(String jdbcUrl) {
59. this.jdbcUrl = jdbcUrl;
60. }
61.
62. public JDBCConnection() {
63. super();
64. }
65. /**
66. * Get the Connection
67. * @return connection
68. * @throws JasperReportException
69. */
70. public Connection getConnection() throws JasperReportException {
71. Connection con;
72. try {
73. check();
74. Class.forName(this.jdbcDriver);
75. con = DriverManager.getConnection(this.jdbcUrl, this.dbUser, this.dbPassword);
76. return con;
77. } catch (Exception e) {
78. e.printStackTrace();
79. throw new JasperReportException("Get JDBC Connection Error");
80. }
81. }
82.
83. /**
84. * Check the Configure
85. * @throws JasperReportException
86. */
87. private void check() throws JasperReportException {
88. if (this.jdbcDriver == null || this.jdbcDriver.equals("") || this.jdbcUrl == null || this.jdbcUrl.equals("")
89. || this.dbUser == null || this.dbUser.equals("") || this.dbPassword == null) {
90. throw new JasperReportException("Jdbc Configure error!");
91. }
92. }
93.
94. }
95.
java 代码
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report.dataSource;
6.
7. import net.sf.jasperreports.engine.JRDataSource;
8. import net.sf.jasperreports.engine.JRException;
9. import net.sf.jasperreports.engine.JRField;
10.
11. /**
12. * 报表的 dataSource 的基类,所有利用 DataSource 产生报表的继承此类
13. */
14. public abstract class ReportDataSource implements JRDataSource {
15.
16. /**
17. * 取值
18. */
19. public abstract Object getFieldValue(JRField jrField) throws JRException;
20.
21. /**
22. * 指针移动
23. */
24. public abstract boolean next() throws JRException;
25.
26. }
27.
这样可以共用配置文件中的 jdbc 连接的相关参数。
对于其它的数据源,JavaBean Collection,笔者采用了一个抽象类,使用抽象类的目的,是为了使开发者尽可能不用直接接触 jasperReport(此为笔者自己的方式,笔者是 PM,为了考虑底下的人的开发)。以下为抽象类以及笔者提供的一个 sample:
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report.dataSource;
6.
7. import java.util.ArrayList;
8. import java.util.List;
9.
10. import net.sf.jasperreports.engine.JRException;
11. import net.sf.jasperreports.engine.JRField;
12.
13. /**
14. * 利用JavaBean Collection生成ReportDataSource的例子
15. */
16. public class ReportDataSourceSample extends ReportDataSource {
17.
18. private List docs = new ArrayList();
19.
20. private int index = -1;
21.
22. public ReportDataSourceSample() {
23. for (int i = 0; i < 10; i++) {
24. Document doc = new Document("ViewTimes is:" + i, i);
25. this.docs.add(doc);
26. }
27. }
28.
29. // 内部类,作为demo时使用
30. private class Document {
31. private String name;
32.
33. private int viewTimes;
34.
35. public String getName() {
36. return name;
37. }
38.
39. public void setName(String name) {
40. this.name = name;
41. }
42.
43. public int getViewTimes() {
44. return viewTimes;
45. }
46.
47. public void setViewTimes(int viewTimes) {
48. this.viewTimes = viewTimes;
49. }
50.
51. public Document() {
52. }
53.
54. public Document(String name, int viewTimes) {
55. this.name = name;
56. this.viewTimes = viewTimes;
57. }
58. }
59.
60. public List getDocs() {
61. return docs;
62. }
63.
64. public void setDocs(List docs) {
65. this.docs = docs;
66. }
67.
68. @Override
69. public Object getFieldValue(JRField jrField) throws JRException {
70.
71. String fieldName = jrField.getName();
72. Document doc = this.docs.get(index);
73. if ("name".equals(fieldName)) {
74. return doc.getName();
75. }
76. if ("viewTimes".equals(fieldName)) {
77. return doc.getViewTimes();
78. }
79. return null;
80. }
81.
82. @Override
83. public boolean next() throws JRException {
84. index++;
85. return (index < this.docs.size());
86. }
87. }
88.
java 代码
以上的例子应当很清楚的写明了如何生成数据源。
对于数据源的填充,笔者使用了二个类,分别用来对应使用 Connction 及 JavaBean Collection 进行填充。
java 代码
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report.jasperPrint;
6.
7. import java.io.File;
8. import java.sql.Connection;
9. import java.util.Map;
10.
11. import net.sf.jasperreports.engine.JRException;
12. import net.sf.jasperreports.engine.JasperFillManager;
13. import net.sf.jasperreports.engine.JasperPrint;
14. import net.sf.jasperreports.engine.JasperReport;
15. import net.sf.jasperreports.engine.util.JRLoader;
16. import cn.com.reachway.framework.exception.JasperReportException;
17.
18. /**
19. * 使用报表模板及数据等来生成 JapserPrint
20. */
21. public class JasperPrintWithConnection {
22. /** 传入的参数 */
23. private Map params;
24. /** 模板文件的地址 */
25. private String reportFilePath;
26. /** JDBC connection */
27. private Connection con;
28.
29. public Connection getCon() {
30. return con;
31. }
32.
33. public void setCon(Connection con) {
34. this.con = con;
35. }
36.
37. public Map getParams() {
38. return params;
39. }
40.
41. public void setParams(Map params) {
42. this.params = params;
43. }
44.
45. public String getReportFilePath() {
46. return reportFilePath;
47. }
48.
49. public void setReportFilePath(String reportFilePath) throws JasperReportException {
50. if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))
51. throw new JasperReportException("您传入的模板文件格式不对,请传入以.jasper 为后缀的文件!");
52. this.reportFilePath = reportFilePath;
53. }
54.
55. public JasperPrintWithConnection() {
56. super();
57. }
58.
59. public JasperPrintWithConnection(String reportFilePath, Map params, Connection con) throws JasperReportException {
60. if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))
61. throw new JasperReportException("模板文件格式不对,请传入以 .jasper 为后缀的文件!");
62. if (con == null)
63. throw new JasperReportException("Conncetion 不应当为null!");
64. this.setReportFilePath(reportFilePath);
65. this.setParams(params);
66. this.setCon(con);
67. }
68.
69. /**
70. * 取得JasperPrint
71. * @return
72. * @throws JasperReportException
73. */
74. public JasperPrint getJasperPrint() throws JasperReportException {
75. File reportFile = new File(this.reportFilePath);
76. if (!reportFile.exists())
77. throw new JasperReportException("传入的模板文件不存在!");
78.
79. try {
80. // Load编译好的模板
81. JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());
82. // 进行数据填充
83. JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, this.params, this.con);
84. return jasperPrint;
85.
86. } catch (JRException jre) {
87. jre.printStackTrace();
88. throw new JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数 map 有误!");
89. }
90.
91. }
92. }
93.
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report.jasperPrint;
6.
7. import java.io.File;
8. import java.util.Map;
9.
10. import net.sf.jasperreports.engine.JRDataSource;
11. import net.sf.jasperreports.engine.JRException;
12. import net.sf.jasperreports.engine.JasperFillManager;
13. import net.sf.jasperreports.engine.JasperPrint;
14. import net.sf.jasperreports.engine.JasperReport;
15. import net.sf.jasperreports.engine.util.JRLoader;
16. import cn.com.reachway.framework.exception.JasperReportException;
17.
18. /**
19. *
20. */
21. public class JasperPrintWithDataSource {
22. /** 传入的参数 */
23. private Map params;
24. /** 模板文件的地址 */
25. private String reportFilePath;
26. /** dataSrouce */
27. private JRDataSource dataSource;
28.
29. public JRDataSource getDataSource() {
30. return dataSource;
31. }
32.
33. public void setDataSource(JRDataSource dataSource) {
34. this.dataSource = dataSource;
35. }
36.
37. public Map getParams() {
38. return params;
39. }
40.
41. public void setParams(Map params) {
42. this.params = params;
43. }
44.
45. public String getReportFilePath() {
46. return reportFilePath;
47. }
48.
49. public void setReportFilePath(String reportFilePath) throws JasperReportException {
50. if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))
51. throw new JasperReportException("您传入的模板文件格式不对,请传入以 .jasper 为后缀的文件!");
52. this.reportFilePath = reportFilePath;
53. }
54.
55. public JasperPrintWithDataSource() {
56. super();
57. }
58.
59. public JasperPrintWithDataSource(String reportFilePath, Map params, JRDataSource dataSource)
60. throws JasperReportException {
61. if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))
62. throw new JasperReportException("模板文件格式不对,请传入以 .jasper 为后缀的文件!");
63. if (dataSource == null)
64. throw new JasperReportException("DataSource 不应当为 null!");
65. this.setReportFilePath(reportFilePath);
66. this.setParams(params);
67. this.setDataSource(dataSource);
68. }
69. /**
70. * 取得 JasperPrint
71. * @return
72. * @throws JasperReportException
73. */
74. public JasperPrint getJasperPrint() throws JasperReportException {
75. File reportFile = new File(this.reportFilePath);
76. if (!reportFile.exists())
77. throw new JasperReportException("传入的模板文件不存在!");
78.
79. try {
80. // Load 编译好的模板
81. JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());
82. // 进行数据填充
83. JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, this.params, this.dataSource);
84. return jasperPrint;
85.
86. } catch (JRException jre) {
87. jre.printStackTrace();
88. throw new JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数 map 有误!");
89. }
90.
91. }
92. }
93.
java 代码
其中使用的 JasperReportException 为笔者定义的异常,用来统一处理报表异常。
5、报表产生
报表产生是程序中最终可见的一部分,在 jasperReport 的 demo 中,大部分中使用了 jasperReport 的 net.sf.jasperreports.j2ee.servlets.*中的类来生成。其实这也算是开源的产品的一个问题,其实 jasperReport 提供的 report 的工具,只能算是 demo 级别的,不能算是产品级别的。相信很多的朋友在使用的时候就碰上无法生成的问题。笔者在此基础上封装了一下。
具体参见以下:
Java 代码
1. /**
2. * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.
3. * @author Jimmy.Shine
4. */
5. package cn.com.reachway.framework.report.export;
6.
7. import java.io.IOException;
8. import java.io.PrintWriter;
9. import java.sql.Connection;
10. import java.util.Map;
11.
12. import javax.servlet.http.HttpServletRequest;
13. import javax.servlet.http.HttpServletResponse;
14.
15. import net.sf.jasperreports.engine.JRDataSource;
16. import net.sf.jasperreports.engine.JRExporterParameter;
17. import net.sf.jasperreports.engine.JasperPrint;
18. import net.sf.jasperreports.engine.export.JRHtmlExporter;
19. import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
20. import net.sf.jasperreports.j2ee.servlets.ImageServlet;
21. import cn.com.reachway.framework.exception.JasperReportException;
22. import cn.com.reachway.framework.report.jasperPrint.JasperPrintWithConnection;
23. import cn.com.reachway.framework.report.jasperPrint.JasperPrintWithDataSource;
24.
25. /**
26. * 利用报表生成 HTML 格式报表
27. */
28. public class HTMLExport {
29.
30. /**
31. * 导出报表
32. *
33. * @param request
34. * @param response
35. * @param reportFilePath
36. * @param params
37. * @param con
38. * @throws JasperReportException
39. */
40. public void export(HttpServletRequest request, HttpServletResponse response, String reportFilePath, Map params,
41. Connection con) throws JasperReportException {
42. try {
43. PrintWriter out = response.getWriter();
44. try {
45. response.setContentType("text/html;charset=UTF-8");
46. JasperPrint jasperPrint = new JasperPrintWithConnection(reportFilePath, params, con).getJasperPrint();
47. // 使用JRHtmlExproter导出 Html 格式
48. JRHtmlExporter exporter = new JRHtmlExporter();
49. request.getSession().setAttribute(ImageServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
50. exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
51. exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
52. exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "./servlets/image?image=");
53. exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
54. // 导出
55. exporter.exportReport();
56. } catch (Exception e) {
57. e.printStackTrace();
58. throw new JasperReportException("在导出 Html 格式报表时发生错误!");
59. } finally {
60. if (out != null) {
61. try {
62. out.close();
63. } catch (Exception e) {
64. }
65. }
66. }
67. } catch (IOException ioe) {
68. ioe.printStackTrace();
69. throw new JasperReportException("从 Response 中取得 P
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com
文章转载自:JavaEye