好,本篇开始讲解如何利用设计好的jasper报表来付诸应用,即在Web应用中如何调用jasper报表文件。
首先运行Netbean IDE 6.8,并创建一个Web应用的工程。如何在Netbean IDE创建Web应用工程,包括如何使用Netbean IDE可以参考我写的《NetBeanIDE 6如何安装和使用》文章,这篇文章在我博客日志的”NetbeanIDE“分类中,时间是2007-12-04,如果需要可以去参考。
要要把jasper的包加入到/WEN-INF/lib中
需要的类在ireport的安装目录下:
iReport-3.7.3\ireport\modules\ext(如果为3.7.3):
jasperreports-3.7.3.jar
iText-2.1.7.jar
groovy-all-1.5.5.jar
commons-digester-1.7.jar
commons-collections-3.2.1.jar
commons-beanutils-1.8.2.jar
根据我的测试需要以上这些包,如果不够请在这个目录下寻找。
在WEB-INF下新建文件夹 report,把ireport下生成的meeting_phone_list.jasper放到这个目录下
其次,打开index.jsp文件,在其中填写如下代码:
<form action="SReport" id="frmPrintView" name="frmPrintView" method="post" target="_blank"> <input type="hidden" name="export_type" value="pdf"> <input type="hidden" name="report" value="meeting_phone_list"> <input type="hidden" name="meeting_name" value="江西省南昌市工业管理局"> <input type="submit" value="打印"> </form> |
接下来,建立report.servlet的包,在此包下面建立SReport类,此类是一个Servlet类。修改其中processRequest方法。processRequest方法里的实现思路
: 1)获取前台传入的参数,这些参数包括“export_type”(导出文件格式)、“report”(报表文件名)、“meeting_name”(会议名称)。
2)填充报表。通过JasperFillManager类的fillReport方法来填充。
3)依据导出文件格式要求不同产生不同的字节对象,可以支持的导出文件格式包括“pdf”、“excel”、“html”、“xml”。
4)通过response对象向前台输出。
其具体代码如下:
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置字符集 request.setCharacterEncoding("GBK"); //获取导出文件类型 String export_type=request.getParameter("export_type")==null?"pdf":(String)request.getParameter("export_type"); //获取报表名 String report_file=request.getParameter("report")==null?"":(String)request.getParameter("report"); Hashtable ht=new Hashtable(); java.util.Collection collection=null; //针对不同报表进行不同处理 if(report_file.equals("meeting_phone_list")){ System.out.println("当前报表名:"+report_file); String meeting_name=request.getParameter("meeting_name")==null?"":(String)request.getParameter("meeting_name"); //将报表名取出,放入Map类对象中,方便之后传入报表 ht.put("meeting_name", meeting_name); //BMeetingPhoneListDS为自定义的活动数据的类。 BMeetingPhoneListDS mpl_ds=new BMeetingPhoneListDS(); //获得数据,数据为java.util.Collection类型 collection=mpl_ds.getCollection(); } //因为是基于JavaBean数据源的,因此采用JRBeanCollectionDataSource类 JRBeanCollectionDataSource ds=new JRBeanCollectionDataSource(collection); ServletOutputStream ouputStream =null; byte[] bReport=null; String err=null; try { StringBuffer sb=new StringBuffer("/WEB-INF/report/"); sb.append(report_file); sb.append(".jasper"); ServletContext application=this.getServletContext(); String cd=application.getRealPath(sb.toString()); System.out.println("当前路径:"+cd); JasperPrint jasperPrint = null; //将参数置入报表,参数包括报表文件路径、报表接收的传入参数(以Map类提供)、报表数据源 jasperPrint = JasperFillManager.fillReport(cd, ht, ds); System.out.println("填充报表......"); //依据导出文件格式不同,配置不同参数 if(export_type.toLowerCase().equals("pdf")){ bReport = JasperExportManager.exportReportToPdf(jasperPrint); } else{ if(export_type.toLowerCase().equals("excel")){ JRXlsExporter exporter = new JRXlsExporter(); ByteArrayOutputStream oStream = new ByteArrayOutputStream(); exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, oStream); exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,Boolean.TRUE); exporter.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET,Boolean.FALSE); exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,Boolean.FALSE); exporter.exportReport(); bReport= oStream.toByteArray(); oStream.close(); } else{ if(export_type.toLowerCase().equals("html")){ JRHtmlExporter exporter = new JRHtmlExporter(); ByteArrayOutputStream oStream = new ByteArrayOutputStream(); exporter.setParameter(JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN,Boolean.FALSE); exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint); exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK"); exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, oStream); exporter.exportReport(); bReport= oStream.toByteArray(); oStream.close(); } else{ bReport = JasperExportManager.exportReportToXml(jasperPrint).getBytes(); } } } } catch(Exception e){ err=e.getMessage(); System.out.println("制作报表失败!原因:"+err); bReport=null; } try{ if(bReport!=null){ //response.setContentType("application/octet-stream;charset=UTF-8"); //将数据输出到客户端 response.setContentType("application/pdf;charset=GBK"); response.setCharacterEncoding("GBK"); //设置客户端接收到的文件的文件名。 String filename="222222.pdf"; response.addHeader("Content-Disposition", "inline; filename="+filename); ouputStream = response.getOutputStream(); response.setContentLength(bReport.length); ObjectOutputStream oos = new ObjectOutputStream(ouputStream); //oos.writeObject(jasperPrint); ouputStream.write(bReport, 0, bReport.length); oos.flush(); oos.close(); } else{ PrintWriter pw=response.getWriter(); pw.print(err); pw.close(); } } catch(Exception e){ System.out.println("输出报表失败!原因:"+e.getMessage()); } finally { try{ if(ouputStream!=null){ ouputStream.close(); ouputStream=null; } } catch(Exception e){ } } }
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response); } |
上面我们实现了Servlet,但此次Servlet只是接受前端参数,并调用JasperReport的类实现产生报表文件,而数据的源部分需要我们自己编写完成。
下面附上Servlet在Web.xml文件中的配置信息。
<servlet> <servlet-name>SReport</servlet-name> <servlet-class>report.servlet.SReport</servlet-class> </servlet> <servlet-mapping> <servlet-name>SReport</servlet-name> <url-pattern>/SReport</url-pattern> </servlet-mapping> |
由上面的Servlet代码可以看到,在调用JasperFillManager.fillReport方法时,除了第一、二个参数外,我们的数据源需要转换成JRBeanCollectionDataSource类的对象,而JRBeanCollectionDataSource类又是由Collection构造而来。我们可以想到,为了还有很多的报表要基于此Servlet来实现,因此为了稍微通用点,我们首先来定义一个接口:
package report; import java.util.ArrayList; /** * * @author 伏虎 */ public interface IDataSource<T> { public ArrayList<T> getCollection(); } |
然后,定义一个Javabean用来实现POJO,相当于一条记录。
package report; /** * * @author 伏虎 */ public class CAddressList { private int id=0; private String name=null; private String post=null; private String sex=null; private String nationality=null; private String phone=null; private String unit=null; public String getUnit() { return unit; } public void setUnit(String unit) { this.unit = unit; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNationality() { return nationality; } public void setNationality(String nationality) { this.nationality = nationality; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getPost() { return post; } public void setPost(String post) { this.post = post; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } } |
在定义一个商业类来获取或者产生数据,我这里是通过此商业方法产生数据(因为做演示)
package report; import java.util.ArrayList; import java.util.Random; /** * * @author 伏虎 */ public class BMeetingPhoneListDS implements IDataSource<CAddressList> { public ArrayList<CAddressList> getCollection() { Random r=new Random(); int p=r.nextInt(25); int max=80; int step=p; int loop=0; int index=0; ArrayList<CAddressList> rtn = new ArrayList<CAddressList>(); for (int i = 1; i <= max; i++) { CAddressList bean = new CAddressList(); bean.setId(i); if(loop>step){ index++; loop=0; } else{ loop++; } bean.setUnit("工作单位"+index); bean.setName("姓名"+i); bean.setPost("岗位"+i); if((i % 2)==0){ bean.setSex("女"); } else{ bean.setSex("男"); } bean.setNationality("民族"+i); bean.setPhone("电话"+i); rtn.add(bean); } return rtn; } } |
好到此,服务端的实现基本就完成了。
现在运行,点击页面上的答应按钮就可以看到会弹出一个窗口并在其中显示报表。当然如果你导出的是pdf文件,则客户端要求安装Adobe的Reader阅读器。