一次 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流,以返还给请求客户端。源码:

  1. package com.defonds.test;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.ObjectOutputStream;  
  6.   
  7. import javax.servlet.RequestDispatcher;  
  8. import javax.servlet.ServletException;  
  9. import javax.servlet.ServletOutputStream;  
  10. import javax.servlet.http.HttpServlet;  
  11. import javax.servlet.http.HttpServletRequest;  
  12. import javax.servlet.http.HttpServletResponse;  
  13. import java.sql.Connection;  
  14. import java.sql.DriverManager;  
  15. import java.sql.ResultSet;  
  16. import java.sql.SQLException;  
  17. import java.sql.Statement;  
  18. import java.util.Calendar;  
  19. import java.util.HashMap;  
  20. import java.util.Map;  
  21.   
  22. import net.sf.jasperreports.engine.JRResultSetDataSource;  
  23. import net.sf.jasperreports.engine.JasperCompileManager;  
  24. import net.sf.jasperreports.engine.JasperExportManager;  
  25. import net.sf.jasperreports.engine.JasperFillManager;  
  26. import net.sf.jasperreports.engine.JasperPrint;  
  27. import net.sf.jasperreports.engine.JasperReport;  
  28. import net.sf.jasperreports.engine.JasperRunManager;  
  29.   
  30. /** 
  31.  * 建立数据库链接 
  32.  * 由 sql 语法取出资料,准备好传入的 parameters 
  33.  * 将 parameters 及取出的资料传入 Jasper 中。会由 .jasper 文档生出 .jrprint 文档 
  34.  * 再由 .jrprint 文档生出 .pdf 目的文档给调用页面下载 
  35.  * @author Defonds 
  36.  * 
  37.  */  
  38. public class TestServlet3 extends HttpServlet {  
  39.    
  40.  private static final String CONTENTTYPE = "application/octet-stream";   
  41.   
  42.     /** 
  43.      * Constructor of the object. 
  44.      */  
  45.     public TestServlet3() {  
  46.         super();  
  47.     }  
  48.   
  49.     /** 
  50.      * Destruction of the servlet. <br> 
  51.      */  
  52.     public void destroy() {  
  53.         super.destroy(); // Just puts "destroy" string in log  
  54.         // Put your code here  
  55.     }  
  56.   
  57.     /** 
  58.      * The doGet method of the servlet. <br> 
  59.      * 
  60.      * This method is called when a form has its tag value method equals to get. 
  61.      *  
  62.      * @param request the request send by the client to the server 
  63.      * @param response the response send by the server to the client 
  64.      * @throws ServletException if an error occurred 
  65.      * @throws IOException if an error occurred 
  66.      */  
  67.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  68.             throws ServletException, IOException {  
  69.      String fileName = "";  
  70.      String sql = "";  
  71.      Map parameters = new HashMap();  
  72.      //parameters.put("rptToday", strDate);//传入的 prameters 引数  
  73.      sql = "select * from tab_channel_car_basic t";  
  74.        
  75.      Connection conn = this.createConnection();//建立连接  
  76.      try {  
  77.       Statement stmt = conn.createStatement();  
  78.       ResultSet rs = stmt.executeQuery(sql);  
  79.       response.setContentType(CONTENTTYPE);    
  80.       ServletOutputStream ouputStream = response.getOutputStream();    
  81.       fileName="D://iReport//iReport-0.4.0//Work//carBasic3.jrxml";  
  82.       JasperReport jrt = JasperCompileManager.compileReport(fileName);//编译报表格式   
  83.       JasperPrint jpt = JasperFillManager.fillReport(jrt, parameters, new JRResultSetDataSource(rs));//匹配数据源,生成JasperPrint  
  84.       ObjectOutputStream oos = new ObjectOutputStream(ouputStream);   
  85.       oos.writeObject(jpt);      
  86.             oos.flush();      
  87.             oos.close();   
  88.   
  89.   
  90.      }catch(Exception e) {  
  91.       System.out.println("Error:" + e.toString());  
  92.       e.printStackTrace();  
  93.      }finally {  
  94.       CloseConnect(conn);  
  95.       conn = null;  
  96.      }  
  97.        
  98.     }  
  99.        
  100.     /** 
  101.      * 建立连接方法 
  102.      * @return Connection 
  103.      */  
  104.      public Connection createConnection() {  
  105.       Connection conn;  
  106.       try {  
  107.        String driver = "oracle.jdbc.driver.OracleDriver";  
  108.        String url = "jdbc:oracle:thin:@localhost:1521:CUC";  
  109.        Class.forName(driver);  
  110.        conn = DriverManager.getConnection(url,"sybj","sybj");  
  111.        conn.setAutoCommit(false);  
  112.        return conn;  
  113.       }catch(SQLException e1) {  
  114.        System.out.println("建立连接错误 = " + e1.toString());  
  115.        e1.printStackTrace();  
  116.       }catch(ClassNotFoundException e2) {  
  117.        System.out.println("建立连接错误 = " + e2.toString());  
  118.        e2.printStackTrace();  
  119.       }  
  120.       return null;  
  121.      }  
  122.        
  123.     /** 
  124.      * 关闭连接方法 
  125.      * @param conn 
  126.      */   
  127.     public void CloseConnect(Connection conn) {  
  128.      try {  
  129.       conn.commit();  
  130.       conn.setAutoCommit(true);  
  131.       conn.close();  
  132.      }catch(Exception e) {  
  133.       System.out.println("关闭连接错误 = " + e.toString());  
  134.      }  
  135.     }  
  136.       
  137.   
  138. }  
PS:这里,关于 carBasic3.jrxml 文件的提取,笔者采用的是物理路径,读者可以把 *.jrxml 文件放到项目根目录下,然后采用其他方式提取。
如果输入
http://localhost:9999/Test2/testServlet3 就弹出来一个下载窗口,证明这个 servlet 已经 ok(笔者 tomcat 端口号设置的是 9999,在 Test2 项目中进行测试)。
7、applet 请求服务器 servlet 得到 JasperPrint 对象并打印。源码:

package com.defonds.test;  
  1. import java.applet.Applet;  
  2. import java.io.PrintWriter;  
  3. import java.io.StringWriter;  
  4. import java.net.URL;  
  5.   
  6. import javax.swing.JOptionPane;  
  7.   
  8. import net.sf.jasperreports.engine.JasperPrint;  
  9. import net.sf.jasperreports.engine.JasperPrintManager;  
  10. import net.sf.jasperreports.engine.util.JRLoader;  
  11.   
  12. public class JRPrinterApplet extends javax.swing.JApplet      
  13. {      
  14.      
  15.      
  16.     /**    
  17.      *    
  18.      */     
  19.     private URL url = null;      
  20.     private JasperPrint jasperPrint = null;      
  21.      
  22.      
  23.     /** Creates new form AppletViewer */     
  24.     public JRPrinterApplet()      
  25.     {      
  26.               
  27.     }      
  28.      
  29.      
  30.     /**    
  31.     *    
  32.     */     
  33.     public void init()      
  34.     {      
  35. //        String strUrl = getParameter("REPORT_URL");      
  36.      String strUrl = "http://localhost:9999/Test2/testServlet3";  
  37.         if (strUrl != null)      
  38.         {      
  39.             try     
  40.             {      
  41.                 //url = new URL(getCodeBase(), strUrl);      
  42.              URL urll = new URL("http://localhost:9999/Test2/testServlet3");  
  43.              url = urll;  
  44.        System.out.println("url="+urll);  
  45.             }      
  46.             catch (Exception e)      
  47.             {      
  48.                 StringWriter swriter = new StringWriter();      
  49.                 PrintWriter pwriter = new PrintWriter(swriter);      
  50.                 e.printStackTrace(pwriter);      
  51.                 JOptionPane.showMessageDialog(this, swriter.toString());      
  52.             }      
  53.         }      
  54.         else     
  55.         {      
  56.         JOptionPane.showMessageDialog(this"init():Source URL not specified");      
  57.         }      
  58.     }      
  59.      
  60.     public void start() {      
  61.         if (url != null)      
  62.         {      
  63.             if (jasperPrint == null)      
  64.             {      
  65.                 try     
  66.                 {      
  67.                  System.out.println("进入start方法,即将下载pdf文件");  
  68.                     jasperPrint = (JasperPrint)JRLoader.loadObject(url);    
  69.                     System.out.println("进入start方法,下载pdf文件完毕");  
  70.                 }      
  71.                 catch (Exception e)      
  72.                 {      
  73.                     StringWriter swriter = new StringWriter();      
  74.                     PrintWriter pwriter = new PrintWriter(swriter);      
  75.                     e.printStackTrace(pwriter);      
  76.                     JOptionPane.showMessageDialog(this, swriter.toString());      
  77.                 }      
  78.             }      
  79.                   
  80.             if (jasperPrint != null)      
  81.             {                     
  82.                 final JasperPrint print = jasperPrint;      
  83.                       
  84.                 Thread thread = new Thread      
  85.                     (      
  86.                         new Runnable()      
  87.                         {      
  88.                             public void run()      
  89.                             {      
  90.                                 try       
  91.                                 {      
  92.                                  System.out.println("进入start方法,即将打印pdf文件");  
  93.                                     JasperPrintManager.printReport(print, true);      
  94.                                 }      
  95.                                 catch (Exception e)       
  96.                                 {      
  97.                                     StringWriter swriter = new StringWriter();      
  98.                                     PrintWriter pwriter = new PrintWriter(swriter);      
  99.                                     e.printStackTrace(pwriter);      
  100.                                     JOptionPane.showMessageDialog(null, swriter.toString());      
  101.                                 }      
  102.                             }      
  103.                         }      
  104.                     );      
  105.                       
  106.                 thread.start();      
  107.             }      
  108.             else     
  109.             {      
  110.                 JOptionPane.showMessageDialog(this"Empty report.");      
  111.             }      
  112.         }      
  113.         else     
  114.         {      
  115.             JOptionPane.showMessageDialog(this"start():Source URL not specified");      
  116.         }      
  117.      
  118.     }      
  119.           
  120. }  

 

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

 

  1. <%@ page language="java" import="java.util.*" pageEncoding="GBK"%>  
  2. <%  
  3. String path = request.getContextPath();  
  4. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  5. %>  
  6.   
  7. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  8. <html>  
  9.   <head>  
  10.     <base href="<%=basePath%>">  
  11.       
  12.     <title>My JSP 'index.jsp' starting page</title>  
  13.  <meta http-equiv="pragma" content="no-cache">  
  14.  <meta http-equiv="cache-control" content="no-cache">  
  15.  <meta http-equiv="expires" content="0">      
  16.  <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  17.  <meta http-equiv="description" content="This is my page">  
  18.  <!-- 
  19.  <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css"> 
  20.  -->  
  21. </head>   
  22. <mce:script language="javascript"><!--  
  23.    
  24. function openApp()   
  25. {   
  26. var url = "/JRPrintServlet";   
  27. document.write('<APPLET ID="JrPrt" CODE="com.defonds.test.JRPrinterApplet.class" CODEBASE = "./" ARCHIVE = "reportprint.jar" WIDTH = "0" HEIGHT = "0">');   
  28. document.write('<PARAM NAME = "type" VALUE="application/x-java-applet;version=1.2.2">');   
  29. document.write('<PARAM NAME = "scriptable" VALUE="false">');   
  30. document.write('<PARAM NAME = "REPORT_URL" VALUE ="'+url+'">');   
  31. document.write('</APPLET>');   
  32. }  
  33. // --></mce:script>   
  34. <body bgcolor="#FFFFFF">   
  35. <input type="button" value="测试打印" onclick="openApp();">   
  36.   
  37. </body>   
  38. </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 -validity 36500
还是用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)”异常。笔者查了下资料,没弄明白怎么回事。但这并不影响打印。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值