利用jasperReport制作web报表
作者:54dabang
E-mail:[email protected]
一 前言
一直发现在网上寻找资源比较繁琐,前段时间在制作jasperReport报表时候出现了很多问题。特别是在一些细节方面,特别耗费时间。特此写下此文,希望对和我一样在初期阶段学习的同学能少走一些弯路。
二 内容简介
1)给出自己制作的jasperReport的视图效果,方便对报表工具初期学习的选择。
2)自己制作报表的测试源码和所有相关学习资料,对应所有jar包,jasperReport版本。
3)快速开发报表的一些建议,为方便学习者快速开发,本文特封装了通用接口。
4)在linux下部署jasperReport出现内存溢出的问题解决方案。
三 jasperReport的视图效果
JasperReport支持多种数据格式导出,包括excel、pdf、RTF、JXL、ODF、html等。如果在web页面使用我推荐将pdf格式文件嵌入到iframe当中,原因是视觉效果好,只要客户端安装了pdfReader即可在页面上进行打印、预览、保存等操作。
四 相关资料与测试源码
http://zmx.iteye.com/blog/572812
这个博客讲了以 实现JRDataSource接口为数据源,从构造实体类到导出报表的所有过程,而且十分易于上手,并且提供了源代码。我的项目本身也是在此基础上完成的。强烈推荐一下。由于他的项目中存在jar包不全的问题,可以直接下载我的测试项目。需要注意的是我的Ireport版本为3.5.2。最好下载对应版本,否则由于jar包不一致,可能会出现导出报表错误。
我的完整测试例子(重要)下载链接:
http://download.csdn.net/detail/leixingbang1989/8539467
JaperReport官网:
japerReport API(英文版)
http://download.csdn.net/detail/leixingbang1989/8539545
jasperReport各种文档大全(自己收集)含:JasperReport中文用户手册 jaspersoft-studio-user-guide_0.pdf Jasper_+_ireport_集成报表到Web应用_操作说明.doc
iReport中文教程.doc JasperReport+iReport报表工具详细开发手册.doc等。
下载链接 http://download.csdn.net/detail/leixingbang1989/8545885
jasperReport
前台页面:
<%@page contentType="text/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <link rel="stylesheet" type = "text/css" href ="extjs/resources/css/ext-all.css"> <link rel="stylesheet" type="text/css" href="css/ext-input.css"> <script type ="text/javascript" src="extjs/adapter/ext/ext-base.js"> </script> <script type ="text/javascript" src="extjs/ext-all.js"></script> <script type="text/javascript" src="extjs/resources/js/ext-lang-zh_CN.js"></script> <title>测试页面程序</title> </head> <script type="text/javascript"> Ext.onReady(function(){ Ext.useShims=true;//一定要加上这句 否则会出现日期的panel被iframe覆盖 var startdate = new Ext.form.DateField({ fieldLabel: '开始时间', labelStyle : "text-align:right;", id:"awardstartdate", name: 'startdate', width: 100, maxValue:new Date(), allowBlank: false, // 设置非空, altFormats: 'Y-m-d ', format: 'Y-m-d ', listeners: { 'select' : function() { var start = Ext.getCmp('awardstartdate').getValue(); Ext.getCmp('awardenddate').setMinValue(start); var endDate = Ext.getCmp('awardenddate').getValue(); if(start > endDate){ Ext.getCmp('awardendDate').setValue(start); } } }, blankText: 'rrr ...', //如为空,后面会出现一个I的图标,点击后出现的alt内容 value:Date.parseDate('1990-01-01','Y-m-d') //如为空,直接在input中出现的text,有红色边框 }); var enddate = new Ext.form.DateField({ fieldLabel: '结束时间', labelStyle : "text-align:right;", id:"awardenddate", name: 'enddate', width: 100, minValue:Date.parseDate('1990-01-01','Y-m-d'), allowBlank: false, // 设置非空, altFormats: 'Y-m-d ', format: 'Y-m-d ', listeners: { 'select' : function() { var end = Ext.getCmp('awardenddate').getValue(); Ext.getCmp('awardstartdate').setMaxValue(end); var startDate = Ext.getCmp('awardstartdate').getValue(); if(end < startDate){ Ext.getCmp('awardstartDate').setValue(end); } } }, blankText: 'rrr ...', //如为空,后面会出现一个I的图标,点击后出现的alt内容 value: new Date() //如为空,直接在input中出现的text,有红色边框 }); var f=new Ext.form.FormPanel({ id:"awardqueryForm", method:"post", frame:true, renderTo:"researchAward", items:[{ //layout:"column", layout: { type: 'column', pack: 'center', //纵向对齐方式 start:从顶部;center:从中部;end:从底部 align: 'left' //对齐方式 center、left、right:居中、左对齐、右对齐;stretch:延伸;stretchmax:以最大的元素为标准延伸 }, items:[{layout:"form",columnWidth:.15,items:[startdate]}, {layout:"form",columnWidth:.15,items:[enddate]} ] }], buttons:[ { text:"确定", handler:function(){ change(); } }], renderTo:"researchDiv" } ); var gasReportPanel1 = new Ext.Panel({ id:"gasReportPanel1", //height : 800, autoHeight: true, html : "<iframe id='myIframe' frameborder='1' src='PDFServlet' width='800px' height='1000px'></iframe>", region : 'center', renderTo:"researchDiv", listeners: { afterrender: function() {//渲染完成后 } } }); }); var i=0; function change()//通过javascript来控制iframe的数据源,我这里只做演示 { i++; alert(i); var result=i%2; var ifm= document.getElementById("myIframe"); if(result==0) { ifm.src="jsp/viewer.jsp"; //参数可以通过url路径传入 }else { ifm.src="PDFTest"; } setIframeHeight("myIframe"); } </script> <body> <div id="researchDiv" name="researchDiv" align="center"></div> <div align="center" id="frameDiv" name="frameDiv"></div> </body> </html>
后台程序:
package com.mengya.servlet; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; 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 net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRExporterParameter; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.export.JRPdfExporter; import net.sf.jasperreports.engine.export.JRRtfExporter; import net.sf.jasperreports.engine.util.FileBufferedOutputStream; import net.sf.jasperreports.engine.util.JRLoader; import com.jasperReport.dataSource.HorizontalProjectsDataSource; import com.jasperReport.dataSource.PortraitResearchProjectStatusDataSource; import com.jasperReport.dataSource.UiniversityKnowlegeStatusDataSource; import com.jasperReport.dataSource.UniversityAcademyDataSource; import com.jasperReport.dataSource.UniversityPrizeDataSource; import com.jasperReport.dataSource.noSource; import com.lowagie.text.DocumentException; import com.lowagie.text.pdf.PdfReader; import com.lowagie.text.pdf.PdfStamper; import com.mengya.JRDataSource.PersonDataSource; public class PDFTest extends HttpServlet { private ServletContext servletContext; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } private String getRealRealPath(String sourceJapser)//封装获取在web中获取文件路径的方法 { String basePath="/myJasper/"; return this.servletContext.getRealPath(basePath+sourceJapser); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.servletContext= this.getServletConfig() .getServletContext(); File jasperFile = new File(this.getRealRealPath("NCUTtechBulletin.jasper"));//获取文件 Map map=new HashMap(); map.put("startDate", "1990-01-01"); map.put("endDate","2001-01-01"); map.put("subReportUniverstiyACds", new UniversityAcademyDataSource());//学术成果数据源 map.put("subReportUniverstiyACDir",this.getRealRealPath("UniversityAcademyStatus.jasper"));//学术成果jasper路径 map.put("subReportPrizeDS", new UniversityPrizeDataSource ());//科研获奖数据源 map.put("subReportPrizeDir",this.getRealRealPath("UniversityPrizeStatus.jasper"));//科研获奖jasper路径 map.put("subReportKnowlegeDS", new UiniversityKnowlegeStatusDataSource ());//知识产权数据源 map.put("subReportKnowlegeDir",this.getRealRealPath("UiniversityKnowlegeStatus.jasper"));//知识产权jasper路径 map.put("subReportPortraitRPds", new PortraitResearchProjectStatusDataSource ());//纵向项目数据源 map.put("subReportPortraitRPdir",this.getRealRealPath("UniversityPortraitResearchProjectStatus.jasper"));//纵向项目jasper路径 map.put("subReportHorizontalRPds", new HorizontalProjectsDataSource ());//横向项目数据源 map.put("subReportHorizontalRPdir",this.getRealRealPath("horizontalProjects.jasper"));//横向项目jasper路径 noSource s1=new noSource();//注意这里nosource没有任何数据,是主报表的数据源,由于在主报表当中只含有子报表,所以数据源为空 JasperPrint jasperPrint = null; try { JasperReport jasperReport = (JasperReport) JRLoader .loadObject(jasperFile.getPath());//将文件转化为jasperReport类型 jasperPrint = JasperFillManager.fillReport(jasperReport, map, s1);//填充文件 参数 数据源 } catch (JRException e) { e.printStackTrace(); } if (null != jasperPrint) { FileBufferedOutputStream fbos = new FileBufferedOutputStream(); JRPdfExporter exporter = new JRPdfExporter(); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, fbos);//内部实现应该是用的反射 //将内容输出到fbos流中 exporter .setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); try { exporter.exportReport();//导出对应的文件 fbos.close(); if (fbos.size() > 0) { //设置文件格式 response.setContentType("application/pdf"); response.setContentLength(fbos.size()); ServletOutputStream ouputStream = response .getOutputStream(); try { fbos.writeData(ouputStream);//将数据写入网络流当中 fbos.dispose(); ouputStream.flush(); } finally { if (null != ouputStream) { ouputStream.close(); } } } } catch (JRException e1) { e1.printStackTrace(); } finally { if (null != fbos) { fbos.close(); fbos.dispose(); } } } } } 数据源设计: UniversityAcademyDataSource package com.jasperReport.dataSource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.jasperreports.engine.JRDataSource; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRField; public class UniversityAcademyDataSource implements JRDataSource {//实现此接口 jasperReport通过调用此接口来调用我们的数据源 private List dataLst=this.getMapList(); private int index = -1; @Override public Object getFieldValue(JRField field) throws JRException { Object value = null; String fieldName = field.getName(); Map map=(Map)this.dataLst.get(index);//dataLst中含有从数据库中取出的真实数据 if ("BMMC".equals(fieldName)) {//BMMC对应报表的fieldName value = map.get("BMMC"); } else if ("paperNum".equals(fieldName)) { value = Integer.parseInt((String)map.get("paperNum")); } else if ("writeNum".equals(fieldName)) { value = Integer.parseInt((String)map.get("writeNum")); } else if ("EIMagazineNum".equals(fieldName)) { value = Integer.parseInt((String)map.get("EIMagazineNum")); }else if ("EIMeetingNum".equals(fieldName)) { value = Integer.parseInt((String)map.get("EIMeetingNum")); }else if ("ISTPNum".equals(fieldName)) { value = Integer.parseInt((String)map.get("ISTPNum")); }else if ("SCINum".equals(fieldName)) { value = Integer.parseInt((String)map.get("SCINum")); }else if ("CSSCI".equals(fieldName)) { value = Integer.parseInt((String)map.get("CSSCI")); } return value; } @Override public boolean next() throws JRException { // TODO Auto-generated method stub index++; return index < this.dataLst.size(); } public List getMapList() { List lst=new ArrayList(); for(int i=0;i<11;i++) { Map map=new HashMap(); map.put("BMMC", "学院"+i); map.put("paperNum", ""+i); map.put("writeNum", ""+i); map.put("EIMagazineNum",""+i); map.put("EIMeetingNum", ""+i); map.put("ISTPNum", ""+i); map.put("SCINum", ""+i); map.put("CSSCI", ""+i); lst.add(map); } return lst; } } 数据源设计:noSource package com.jasperReport.dataSource; import java.util.ArrayList; import java.util.List; import java.util.Random; import net.sf.jasperreports.engine.JRDataSource; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRField; import com.mengya.servlet.financeInfo; public class noSource implements JRDataSource {//主报表中不含任何数据 private int index = -1; @Override public Object getFieldValue(JRField field) throws JRException { return null; } @Override public boolean next() throws JRException { index++; return index<1;//如果index<2会导致出现一个空白页面 index<3会出现两个 依此类推 } }
五 遇到的问题
1)中文不显示
首先,在用iReport设计报表时将要显示中文数据的地方的属性设置如下: Font name: 宋体 (中文字体)
PDF font name: STSong-Light
PDF Encoding: UniGB-UCS2-H(ChineseSiplified)
PDF Embeded:
2)linux内存溢出
在catlina.sh中加入
JAVA_OPTS="-Xms128m -Xmx1024m -XX:PermSize=128M -XX:MaxPermSize=256M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC“
具体原因见博客
http://www.cnblogs.com/sixiweb/archive/2012/11/25/2787591.html
3)如果报表中含有多个表格,则需要在主报表中创建子报表。如下图所示:
每个子报表需要放到不同的detail中,否则会出现子报表重叠在一起的情况。子报表的数据源在主报表中以参数的形式传入。
六 建议
在设计报表时,想要提高开发速度,没有必要每个都从头设计(比如想要显示中文label,必须设置若干属性才可以),可以直接从我的项目里面copy,也可以设计好一项后在design页面中直接复制。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。