一次 applet 客户端打印 jasperreport 报表任务笔记

为了方便更多的人了解、使用 Java 打印,写了这个!也希望高手们不吝赐教,指出其中的不足之处,帮助我们提高项目性能,谢谢!
背景:.NET 项目中用 webprint3.0 破解版进行打印。客户反映可否不预览、不弹出打印机对话框,点击“打印”按钮后打印机直接打印?
要求:为了使打印精确,不可以使用 IE 的打印功能;另外打印的时候不可以弹出打印预览、打印机对话框,打印机直接打印。
环境:WindowsXP、IE6.0、JDK(JRE)1.6U14、MyEclipse6.5、Tomcat5.5、Oracle10gr2
使用工具:jasperreports-3.0.1、ireport3.1.0、iTextAsian.jar、apache-ant-1.7.1。
解决方案:使用 JasperReport + iReport 生成形如 *.jrxml 报表模板文件,servlet 调用这个 *.jrxml 文件根据指定 sql 语句生成 JasperReport 报表打印文件,客户端 applet 调用服务器 servlet 得到 JasperPrint 报表打印文件后使用 JasperReport 直接打印。
技术难点:pdf 报表的生成、applet 与服务器 servlet 之间的通信、pdf 报表文件的读写操作、applet 打包及其签名。
详细步骤及其关键部分源码展示:
1、JDK 的安装配置。
关于 JDK 的安装,JDK 环境变量 JAVA_HOME、系统环境变量 CLASSPATH、系统环境变量 Path 的配置笔者不再赘述。
2、ant 的安装和配置。
下载:http://ant.apache.org(笔者使用的是apache-ant-1.7.1,已经将 apache-ant-1.7.1-bin.zip 包共享至 csdn 资源)。
配置:ant 无需安装,解压后就算安装完成。但要在系统变量中增加 ANT_HOME 环境变量,变量值为解压缩后的 ant 所在目录。在环境变量 Path 中增加 %ANT_HOME%/bin 目录。
3、JasperReport 的安装和配置。
下载:sf.net(笔者使用的是jasperreports-3.0.1,已经将jasperreports-3.0.1.rar 包共享至作者的 csdn 资源,解压缩后包含 jasperreports-3.0.1.jar、jasperreports-3.0.1-applet.jar、jasperreports-3.0.1-javaflow.jar 三个工具包,足够我们开发报表、打印报表使用了)。
配置:没有必要单独为 JasperReport.jar 文件包设置目录,直接放在 %JAVA_HOME%/lib 目录中即可。然后将 JasperReport-x.x.x.jar 文件添加到操作系统环境变量 CLASSPATH 中即可完成对 JasperReport 的配置。
4、iReport 的安装和配置。
下载:这个大一点,要有 40 M。iReport 比较成熟,很容易就可以下载到它的 zip 格式的文件包(作者使用的是 ireport3.1.0,已经共享 ireport3.1.0.zip 至 csdn 资源,大小 44 M)。iReport 也无需安装,直接解压后就算完成了安装,也无需配置。但是我们需要处理中文用到 iTextAsia.jar,需要从 http://itextpdf.sourceforge.net 下载。下载后将 iTextAsia.jar 放到 iReport 的 lib 目录中即可(笔者共享的 ireport3.1.0.zip 包里自带了一个 iTextAsia.jar,无需单独下载。另外笔者也单独上传了一份 iTextAsia.jar 至 csdn 资源)。
iReport 在装了 ant 以后,直接运行 iReport 目录中的 ireport.bat 即可运行 iReport。
5、根据项目需要使用 iReport 生成 *.jrxml 报表模板文件。
PS:关于第 1-5  步,如果读者弄不太明白,可以去参考裴贺先写的《JasperReport 与 iReport 的配置与使用》。我有个 pdf 版的,已经共享至我的 csdn 资源。
6、新建一 web 项目 Test2。将 iReport 目录 lib 下的所有 jar 包导入。在 servlet 程序中把从数据库得到的数据传入 *.jrxml 文件得到 *.jrprint 文件(这才是我们想要的东西),并把这个对象写入 Stream流,以返还给请求客户端。源码:

package com.defonds.test; import java.io.File; import java.io.IOException; import java.io.ObjectOutputStream; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import net.sf.jasperreports.engine.JRResultSetDataSource; import net.sf.jasperreports.engine.JasperCompileManager; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperReport; import net.sf.jasperreports.engine.JasperRunManager; /** * 建立数据库链接 * 由 sql 语法取出资料,准备好传入的 parameters * 将 parameters 及取出的资料传入 Jasper 中。会由 .jasper 文档生出 .jrprint 文档 * 再由 .jrprint 文档生出 .pdf 目的文档给调用页面下载 * @author Defonds * */ public class TestServlet3 extends HttpServlet { private static final String CONTENTTYPE = "application/octet-stream"; /** * Constructor of the object. */ public TestServlet3() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = ""; String sql = ""; Map parameters = new HashMap(); //parameters.put("rptToday", strDate);//传入的 prameters 引数 sql = "select * from tab_channel_car_basic t"; Connection conn = this.createConnection();//建立连接 try { Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql); response.setContentType(CONTENTTYPE); ServletOutputStream ouputStream = response.getOutputStream(); fileName="D://iReport//iReport-0.4.0//Work//carBasic3.jrxml"; JasperReport jrt = JasperCompileManager.compileReport(fileName);//编译报表格式 JasperPrint jpt = JasperFillManager.fillReport(jrt, parameters, new JRResultSetDataSource(rs));//匹配数据源,生成JasperPrint ObjectOutputStream oos = new ObjectOutputStream(ouputStream); oos.writeObject(jpt); oos.flush(); oos.close(); }catch(Exception e) { System.out.println("Error:" + e.toString()); e.printStackTrace(); }finally { CloseConnect(conn); conn = null; } } /** * 建立连接方法 * @return Connection */ public Connection createConnection() { Connection conn; try { String driver = "oracle.jdbc.driver.OracleDriver"; String url = "jdbc:oracle:thin:@localhost:1521:CUC"; Class.forName(driver); conn = DriverManager.getConnection(url,"sybj","sybj"); conn.setAutoCommit(false); return conn; }catch(SQLException e1) { System.out.println("建立连接错误 = " + e1.toString()); e1.printStackTrace(); }catch(ClassNotFoundException e2) { System.out.println("建立连接错误 = " + e2.toString()); e2.printStackTrace(); } return null; } /** * 关闭连接方法 * @param conn */ public void CloseConnect(Connection conn) { try { conn.commit(); conn.setAutoCommit(true); conn.close(); }catch(Exception e) { System.out.println("关闭连接错误 = " + e.toString()); } } }

PS:这里,关于 carBasic3.jrxml 文件的提取,笔者采用的是物理路径,读者可以把 *.jrxml 文件放到项目根目录下,然后采用其他方式提取。
如果输入http://localhost:9999/Test2/testServlet3 就弹出来一个下载窗口,证明这个 servlet 已经 ok(笔者 tomcat 端口号设置的是 9999,在 Test2 项目中进行测试)。
7、applet 请求服务器 servlet 得到 JasperPrint 对象并打印。源码:

package com.defonds.test; import java.applet.Applet; import java.io.PrintWriter; import java.io.StringWriter; import java.net.URL; import javax.swing.JOptionPane; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperPrintManager; import net.sf.jasperreports.engine.util.JRLoader; public class JRPrinterApplet extends javax.swing.JApplet { /** * */ private URL url = null; private JasperPrint jasperPrint = null; /** Creates new form AppletViewer */ public JRPrinterApplet() { } /** * */ public void init() { // String strUrl = getParameter("REPORT_URL"); String strUrl = "http://localhost:9999/Test2/testServlet3"; if (strUrl != null) { try { //url = new URL(getCodeBase(), strUrl); URL urll = new URL("http://localhost:9999/Test2/testServlet3"); url = urll; System.out.println("url="+urll); } catch (Exception e) { StringWriter swriter = new StringWriter(); PrintWriter pwriter = new PrintWriter(swriter); e.printStackTrace(pwriter); JOptionPane.showMessageDialog(this, swriter.toString()); } } else { JOptionPane.showMessageDialog(this, "init():Source URL not specified"); } } public void start() { if (url != null) { if (jasperPrint == null) { try { System.out.println("进入start方法,即将下载pdf文件"); jasperPrint = (JasperPrint)JRLoader.loadObject(url); System.out.println("进入start方法,下载pdf文件完毕"); } catch (Exception e) { StringWriter swriter = new StringWriter(); PrintWriter pwriter = new PrintWriter(swriter); e.printStackTrace(pwriter); JOptionPane.showMessageDialog(this, swriter.toString()); } } if (jasperPrint != null) { final JasperPrint print = jasperPrint; Thread thread = new Thread ( new Runnable() { public void run() { try { System.out.println("进入start方法,即将打印pdf文件"); JasperPrintManager.printReport(print, true); } catch (Exception e) { StringWriter swriter = new StringWriter(); PrintWriter pwriter = new PrintWriter(swriter); e.printStackTrace(pwriter); JOptionPane.showMessageDialog(null, swriter.toString()); } } } ); thread.start(); } else { JOptionPane.showMessageDialog(this, "Empty report."); } } else { JOptionPane.showMessageDialog(this, "start():Source URL not specified"); } } }

右键单击 JRPrinterApplet.java,选择 “Run as Java Applet”,弹出打印对话框,确认后打印机正常打印,证明 applet 已经编写成功。
8、jsp 页面嵌入 applet源码:

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css"> --> </head> <mce:script language="javascript"><!-- function openApp() { var url = "/JRPrintServlet"; document.write('<APPLET ID="JrPrt" CODE="com.defonds.test.JRPrinterApplet.class" CODEBASE = "./" ARCHIVE = "reportprint.jar" WIDTH = "0" HEIGHT = "0">'); document.write('<PARAM NAME = "type" VALUE="application/x-java-applet;version=1.2.2">'); document.write('<PARAM NAME = "scriptable" VALUE="false">'); document.write('<PARAM NAME = "REPORT_URL" VALUE ="'+url+'">'); document.write('</APPLET>'); } // --></mce:script> <body bgcolor="#FFFFFF"> <input type="button" value="测试打印" οnclick="openApp();"> </body> </html>

9、applet 打包并签名认证。
将 jasperreport 目录下的 jasperreports-3.0.1-applet.jar 解压。在任一磁盘根目录下新建一文件夹 temp,将 jasperreports-3.0.1-applet.jar 解压后的 META-INF、net、default.jasperreports.properties(这个一定要复制,不然会报 NullPointer 异常)全部复制到 temp下,将 test2 项目下的 WEB-INF 下 classes 中的文件 com 也复制到 temp 下。
CMD 命令, E:/temp>
下键入 jar -cvf reportprint.jar *
temp 目录下会生成 reportprint.jar 包。
用keytool生成证书:keytool -genkey -alias printkey -keystore printstore
还是用keytool导出证书:keytool -export -keystore printstore -alias printkey -file print.cer
用jarsigner给reportprint.jar加上数字签名:jarsigner -keystore printstore reportprint.jar printkey
以上都是在命令提示符下运行,printkey和printstore都可以以自己的命名方式来命名。现在在temp下已经有了一个reportprint.jar和一个print.cer,把这两个文件拷贝回项目中,记得还是放在同一个目录下(最好是根目录,即 Test2 项目的 WebRoot 下)。

完成。运行 test2 项目看看结果如何。如果 Java 控制台提示“ClassNotFoundException”,证明 applet 打包路径没有配置好:去查看 JasperReport 类是否被打包,以及 jsp 页面调用 reportprin.jar 是否正确。如果弹出对话框:该应用程序的数字签名无法验证,是否要运行该应用程序?证明数字签名已经可以使用。

PS: 关于第 7-9 步,作者已经共享了 Test2 applet 打印项目源码至 csdn 资源,代码注释的很详细,而且附带 数据库.sql 说明。如果读者读完本博文后对 applet 打印报表还不是很清楚,可以去下载下来看看。

遗留问题:一、不支持 jre 的自动安装。原因:jsp 嵌入 applet 使用的是 <applet> 标签。最好使用 <object> 标签,客户端没装 jre 的话,自动安装。二、Run as java applet 测试时,applet 没有任何问题,打包后运行时,Java 控制台报“Exception occurred during event dispatching:java.lang.NullPointerException: null pData at sun.awt.windows.WComponentPeer._requestFocus(Native Method)”异常。笔者查了下资料,没弄明白怎么回事。但这并不影响打印。

技术交流msn:defonds@hotmail.com

一次 applet 客户端打印 jasperreport 报表任务笔记相关推荐

  1. [转载] 启用和禁用 Reporting Services 的客户端打印和导出文件格式

    启用和禁用 Reporting Services 的导出文件格式: 您可以修改rsreportserver.config,对于SQL Server 2005,它位于C:\Program Files\M ...

  2. java调adobe打印_Java报表工具打印方案集锦 | 改变自己

    本文试图对市面上流行的纯java实现的web报表工具,jasperreport . stylereport .杰表.润乾报表.快逸.finererport为例,分析各报表工具采用的web打印技术的异同 ...

  3. 使用ireport设计jasperreport报表模板

    1.了解ireport与jasperreport的区别. 2.怎样使用ireport绘制报表模板. 3.了解ireport的几个概念. 4.ireport的深入探讨. 1.ireport 是一个专门用 ...

  4. 使用ireport设计jasperreport报表模板,以及简单的设计使用案例

    1.了解ireport与jasperreport的区别. 2.怎样使用ireport绘制报表模板. 3.了解ireport的几个概念. 4.ireport的深入探讨. 1.ireport 是一个专门用 ...

  5. JasperReport报表导出PDF中文不显示的问题

    首先在JasperReport Studio中加载下载好的中文字体:打开设置页面: Window >> Preferences >> Jaspersoft Studio > ...

  6. C#实现调用打印机(打印字符串、打印绘图、打印图片),还差打印水晶报表

    C#实现调用打印机(打印字符串.打印绘图.打印图片),还差打印水晶报表 目的:调用打印机的使用 缺陷:打印的对象不全(还差打印水晶报表),不能实现在插件绘图板中画什么打印什么 改进:同缺陷,希望朋友们 ...

  7. 共享打印机HP1022在客户端打印的时重启打印服务器才能打印

    声明:博客内所有技术性文章都是由作者本人工作经验的总结, 实现过程中有搜索资料为参考的绝不涉嫌抄袭,均为个人习惯的总结 今天公司的共享打印机不工作了,删除队列时其余的可以正常取消,但是状态为正在打印的 ...

  8. 使用Jaspersoft Studio制作JasperReport报表(三)简单的学生分数统计报表

    前面介绍了新建一个报表的基本流程和报表工具的基本使用,现在就不啰嗦了,直接来个简单的报表实战一下 数据准备 1.数据库数据源准备:新建student数据库表,数据包括id,班级,生日,分数,姓名字段, ...

  9. Jasperreport+applet实现客户端打印

    需求:Web应用中,在客户端实现打印功能 可能遇到的问题: [list] [*][b]64bit系统装64bit的jre但是不好使[/b] [*]装32bit的jre就好了 [*][b]打印时出现in ...

最新文章

  1. 慢SQL,压垮团队的最后一根稻草No.92
  2. UWP Composition API - 锁定列的FlexGrid
  3. C++中的NULL与DELPHI中的nil作用相同
  4. BugKuCTF 杂项 这是一张单纯的图片
  5. mysql 查询优化
  6. linux 网络协议栈变化,ZZ Linux网络协议栈学习
  7. 在Ubuntu 18.04 LTS 入门 ROS Melodic 机器人 操作系统
  8. 愚人节谁最皮?华为宣布攻克兽语,小米6复刻版官宣,微信发万元红包...
  9. Halcon基于形状的几何定位函数说明
  10. 整理自己的.net工具库
  11. mysql的简单实用_MySQL的简单实用 手把手教学
  12. 并行语言开发平台 Erlang
  13. ASP.net 连接interbase数据库
  14. linux控制windows关机
  15. Himall商城枚举帮助类EnumHelper(1)
  16. 【励志】知乎热门:我是怎么变自律的?
  17. windows图片和传真查看器打不开的解决办法
  18. java计算人民币整数金额_java 使用BigDecimal进行货币金额计算的操作
  19. Word中的字体大小(几号-几磅)【转】
  20. Linux终端常用命令

热门文章

  1. 中科院计算机技术研究所考研,中科院光电技术研究所计算机技术怎么样
  2. mac系统常用操作指南
  3. 把款软件可以测试双显卡,大胜对手!A6双显卡性能评测
  4. 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api
  5. 英语语法最终珍藏版笔记- 20倒装
  6. html怎么解决gif图放大失真问题
  7. 春季高考计算机基础知识试题答案,2017山东春季高考语文答案|数学答案|英语答案|基础知识答案...
  8. centOS 7 安装 CUPS 打印服务器,安装映美 FP-730K打印机共享
  9. MES管理系统中的批次管理,贯穿了生产制造的整个流程
  10. Hashkey邓超:投资数字金融的三大逻辑和三大视角(全文)