Jasperreport+applet实现客户端打印 servletiReportJasperreportappletjava
程序员文章站
2022-07-03 13:10:23
...
需求:Web应用中,在客户端实现打印功能
可能遇到的问题:
思路:
使用的框架、设备、环境:
资源:
正文:
1. 制作模版
1.1 准备工作
新建一个类,包含需要打印的信息,比如EntityDto,注意要有setter和getter方法
新建一个类,其中包含可以产生Collection<EntityDto>的方法
引入需要的jar,由于自己做的是maven工程,所以只需在pom文件中增加依赖
编写负责打印的类的代码
1.2 制作模版
2. 准备打印机
3. 使用applet打印
如果现在直接调用代码打印会在服务端打印,由于自己开发的时候是服务端和客户端一体,所以可能忽略这个错误。
注意:这个类一定要放在工程的根目录,也就是不存在任何包中,虽然有点不科学,但是在调用的时候如果有包路径是不好使的
写applet类
使用mvc的控制器得到流
编写html代码
最后把编译好的JRPrinterApplet类放在和html同一个文件夹下即可访问,另外注意archive中有的几个包也要和html放在同样的文件夹中
可能遇到的问题:
- 64bit系统装64bit的jre但是不好使
- 装32bit的jre就好了
- 打印时出现invalid header
- 有可能是编译文件时的Jasperreport的jar版本和运行时的不一样
- 打印出出现“attribute 'uuid' is not allowed to appear in element 'jasperreport'”
- 打开JRXML文件,用正则表达式搜索uuid="\w*-\w*-\w*-\w*-\w*",全部删除
- applet访问权限受限
- 在jre的lib\security\java.policy中的grant {...}代码块中增加 permission java.security.AllPermission;
permission java.net.SocketPermission "*", "accept, connect, listen, resolve";
思路:
- 利用iReport制作模版
- 写后台代码,得到JasperPrint并输出到Servlet的流中
- 用applet接受流,并调用打印机打印
使用的框架、设备、环境:
- Spring MVC
- Spring Tool Suite(Eclipse系列的,Eclipse穿了个马甲)
- 打印机EPSON LQ-630K
资源:
- 报表设计软件,用于制作模版,我使用的是iReport-5.0.0-windows-installer http://sourceforge.net/projects/ireport/files/iReport/iReport-5.0.0/
- EPSON LQ-630K驱动http://epson.com.cn/
正文:
1. 制作模版
1.1 准备工作
public class EntityDto { private String name; private String pwd; public EntityDto(){ } public EntityDto(String name, String pwd){ this.name = name; this.pwd = pwd; } //setter和getter方法,一定要有 }
public class EntityDtoFactory { //方法参数可以自行设定 public static Collection<EntityDto> getBeanCollection() throws SSException { List<EntityDto> entityDtos = new ArrayList<EntityDto>(); //自行定义获取结果方法,这里仅仅是一个示例 entityDtos.add(new EntityDto("notesth","name for short")); entityDtos.add(new EntityDto("notesomething","full name")); return entityDtos; } }
<!-- 为了解决此包冲突,提前引入 --> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.1</version> </dependency> <!-- 解决打印时条形码异常类找不到 --> <dependency> <groupId>net.sourceforge.barbecue</groupId> <artifactId>barbecue</artifactId> <version>1.5-beta1</version> </dependency> <!-- 关于打印部分 --> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>4.5.1</version> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>1.7.5</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency>
public class PrintService(){ //需要参数自行设定 public JasperPrint print() { //把制作好的模版文件放在工程的Class文件夹的/iReportTemplate中,比如名字叫report.jrxml,这个文件会在之后制作 InputStream in = readFile("/iReportTemplate/report.jrxml"); Map<String, Object> parameters = new HashMap<String, Object>(); try{ // 设定数据源 JRDataSource dataSource = new JRBeanCollectionDataSource( EntityDtoFactory.getBeanCollection()); // 编译jrxml文件 JasperReport jasperReport = JasperCompileManager .compileReport(in); // 填充数据 JasperPrint jasperPrint = JasperFillManager.fillReport( jasperReport, parameters, dataSource); }catch (JRException e){ e.printStackTrace(); } catch (Exception e){ e.printStackTrace(); } return jasperPrint; } public InputStream readFile(String location){ ClassLoader classLoader = PrintService.class.getClassLoader(); InputStream in = null; if(classLoader != null){ in = classLoader.getResourceAsStream(location); } if(in == null){ in = ClassLoader.getSystemResourceAsStream(location); } return in; } }
1.2 制作模版
- 首先安装iReport-5.0.0-windows-installer
- 新建一个report,如果没有特殊要求就不用选择其他样式的模版,全点击“下一步”
- 在选项卡中选择“工具”--“选项”--“Classpath”,把编译好的EntityDto所在的jar(没有就打一个jar,如果添加文件夹自己试了不好用,原因不明)添加到其中
- 在主面板中,在“Preview”的右侧有一个类似数据库似的图标,点击,选择“JavaBeans Datasource”的选项卡,在输入框中输入类的全名(包括所在包路径),点击“Read attributes”,选择需要的属性,然后点击“Add selected field(s)”,确认
- 在左侧Fields的列表中就可以看到需要的属性了,然后点击把他们拖过来就可以了
- 点击preview,如果没有什么问题就把report.jrxml,report.jasper都拷贝到工程资源文件下的iReportTemplate目录中
2. 准备打印机
- 安装驱动
3. 使用applet打印
如果现在直接调用代码打印会在服务端打印,由于自己开发的时候是服务端和客户端一体,所以可能忽略这个错误。
注意:这个类一定要放在工程的根目录,也就是不存在任何包中,虽然有点不科学,但是在调用的时候如果有包路径是不好使的
public class JRPrinterApplet extends javax.swing.JApplet { private static final long serialVersionUID = -3202655159625012169L; private URL url = null; private JasperPrint jasperPrint = null; int parameter; /** Creates new form AppletViewer */ public JRPrinterApplet() {} /** * */ public void init() { parameter = Integer.valueOf(getParameter("parameter")); try { this.url = new URL( "http", "192.168.1.14", 8080, "/path/" + parameter); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println(url); } } public void start() { if (url != null) { if (jasperPrint == null) { try { JOptionPane.showMessageDialog(this, "before load url"); JOptionPane.showMessageDialog(this, "url:" + url); jasperPrint = (JasperPrint)JRLoader.loadObject(url); JOptionPane.showMessageDialog(this, "after load url"); JOptionPane.showMessageDialog(this, jasperPrint.getPageHeight()); } catch (Exception e) { JOptionPane.showMessageDialog(this, "catch exception"); StringWriter swriter = new StringWriter(); PrintWriter pwriter = new PrintWriter(swriter); e.printStackTrace(pwriter); JOptionPane.showMessageDialog(this, swriter.toString()); } } if (jasperPrint != null) { JOptionPane.showMessageDialog(this, "just in jasperPrint"); final JasperPrint print = jasperPrint; JOptionPane.showMessageDialog(this, "before thread define"); Thread thread = new Thread ( new Runnable() { public void run() { try { JasperPrintManager.printReport(print, true); } catch (Exception e) { StringWriter swriter = new StringWriter(); PrintWriter pwriter = new PrintWriter(swriter); e.printStackTrace(pwriter); JOptionPane.showMessageDialog(null, swriter.toString()); } } } ); JOptionPane.showMessageDialog(this, "before thread start"); thread.start(); JOptionPane.showMessageDialog(this, "already print"); } else { JOptionPane.showMessageDialog(this, "Empty report."); } } else { JOptionPane.showMessageDialog(this, "Source URL not specified"); } } }
@Controller @RequestMapping(value = "/path") public class PrintController { @Autowired private PrintService printService; /** * @author notesth * @date 2013-6-20 * 把需要批量打印的信息输出到response中 * * @param parameter * @throws IOException */ //有需要使用parameter @RequestMapping(value = "{parameter}") public void postBatchPrintExpressBySequence(@PathVariable("parameter") Integer parameter) throws IOException { final String CONTENTTYPE = "application/octet-stream"; this.getResponse().setContentType(CONTENTTYPE); ServletOutputStream ouputStream = this.getResponse().getOutputStream(); try { ObjectOutputStream oos = new ObjectOutputStream(ouputStream); //这里是调用了另外一个servlet,其结果也是返回一个JasperPrint对象 JasperPrint jpt = printService.print(); oos.writeObject(jpt); oos.flush(); oos.close(); } catch (Exception e) { //TODO:处理 } } }
<html> <head> <title>print</title> </head> <body> <applet code="JRPrinterApplet.class" width="300" height ="300" codebase="./" archive="jasperreports4.5.1.jar,commonslogging1.1.1.jar,commonscollections3.1.jar,commons-digester-2.1.jar" > <PARAM NAME="parameter" VALUE="3"> </applet> </body> </html>
最后把编译好的JRPrinterApplet类放在和html同一个文件夹下即可访问,另外注意archive中有的几个包也要和html放在同样的文件夹中
上一篇: java简单的聊天室