欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Jasperreport+applet实现客户端打印 servletiReportJasperreportappletjava 

程序员文章站 2022-07-03 13:10:23
...
需求:Web应用中,在客户端实现打印功能

可能遇到的问题:

  • 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


资源:



正文:

1. 制作模版

1.1 准备工作
  • 新建一个类,包含需要打印的信息,比如EntityDto,注意要有setter和getter方法

  • 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方法,一定要有
    }
    

  • 新建一个类,其中包含可以产生Collection<EntityDto>的方法

  • 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;
    	}
    
    }
    

  • 引入需要的jar,由于自己做的是maven工程,所以只需在pom文件中增加依赖

  • <!-- 为了解决此包冲突,提前引入 -->
    <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打印

    如果现在直接调用代码打印会在服务端打印,由于自己开发的时候是服务端和客户端一体,所以可能忽略这个错误。

    注意:这个类一定要放在工程的根目录,也就是不存在任何包中,虽然有点不科学,但是在调用的时候如果有包路径是不好使的
  • 写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");   
            }   
      
        }   
           
    }   
    

  • 使用mvc的控制器得到流
  • @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代码

  • 
    <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放在同样的文件夹中