前段时间由于项目需要,开始研究基于web的打印技术。因为jatoolsPrint的分页总是有点儿问题,而又没想到解决办法,所以最后决定使用applet。
applet的缺点其实很多,例如浏览器兼容问题,java插件的支持,以及java安全机制的设置等,不过在报表打印上,applet还是非常好用的。
本项目使用的jasper是ireport编译生成的.jasper模板。
jsp页面上的代码如下:
//此函数用来生成applet元素
function openApp()
{
if(!document.applets[0]){
var applet = document.createElement('APPLET');
applet.id = "appletPrint";
//类名(如果有包的话,还要加上包路径)
applet.code = "JRPrinterApplet.class";
//目录名
applet.codebase = "applet";
applet.ARCHIVE = "jasperreports-3.5.2-applet.jar,commons-logging-1.0.2.jar,commons-collections-2.1.jar";
applet.type="application/x-java-applet;version=1.2.2";
applet.width = "0";
applet.height = "0";
//applet_div是页面上的一个隐藏的div,旨在隐藏appelt的显示。
document.getElementById('applet_div').appendChild(applet);
}
}
//此函数用于打印
function printElecWaybill(){
var selRows = gridMgr.getCheckedRows();
var param = "";
if(!selRows || selRows.length == 0){
$.ligerDialog.warn("请至少选择一条数据");
return false;
}
for(var i=0;i<selRows.length;i++){
if(i==0){
param = "?hawbs=" + selRows[0].hawb;
}else
param += "," + selRows[i].hawb;
}
var path = "<%=basePath%>electronicPrint_printWaybills.action"+param;
if(isAppletOK()){
document.applets[0].printReport(path);
}else{
alert('打印程序正在初始化,请稍后再试...');
}
}
JRPrintApplet.java的代码如下:
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import javax.swing.JApplet;
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 JApplet {
/**
*
*/
private static final long serialVersionUID = 1L;
private URL url = null;
public void init() {
}
public void start() {
}
public boolean isOK(){
return true;
}
public void printReport(String path){
if (path != null) {
try {
//此处获得的path为action路径,例如http://localhost:8080/SDBConsole/electronicPrint_printWaybills.action?hawbs=123454
//也可以使用servlet来实现,action其实就是servlet
URL server = new URL( path);// 从获得html参数中获得报表URL
if(server != null){
Object obj = JRLoader.loadObject(server);// 发送对象请求,获得JasperPrint对象,调用servlet对象(试一试能不能直接访问action)
JasperPrintManager.printReport((JasperPrint) obj, true);// 调用方法打印所获得的JasperPrint对象
}
} catch (Exception e) {
e.printStackTrace();
StringWriter swriter = new StringWriter();
PrintWriter pwriter = new PrintWriter(swriter);
e.printStackTrace(pwriter);
JOptionPane.showMessageDialog(this, swriter.toString());
}
} else {
JOptionPane.showMessageDialog(this, "failure!Source URL not specified");
}
}
}
在action中使用jasper模板和数据生成JasperPrint对象:
package com.sdb.print.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.struts2.ServletActionContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.cubebi.util.HttpRespons;
import com.sdb.model.ElectronicWaybill;
import com.sdb.print.service.ElectronicPrintService;
public class ElectronicPrint {
/**
*
*/
private ElectronicPrintService electronicPrintService;
/**
* 需要打印的运单列表
*/
private String[] hawbs;
public JasperPrint printWaybills(){
HttpServletRequest request = ServletActionContext.getRequest();
String hawbStr = request.getParameter("hawbs");
ServletContext context = ServletActionContext.getServletContext();
HttpServletResponse respons = ServletActionContext.getResponse();
/**
* 组装jasperPrint
*/
File reportFile = new File(context.getRealPath("/jasper/sto.jasper"));
//参数
Map<String,Object> paramters = new HashMap<String,Object>();
List<ElectronicWaybill> waybills = null;
if(hawbStr != null && hawbStr.length()>0){
hawbs = hawbStr.split(",");
waybills = electronicPrintService.getWaybillInfoByHawbs(hawbs);
}
JasperPrint jasperPrint = null;
try {
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(new FileInputStream(reportFile));
JRDataSource ds = new JRBeanCollectionDataSource(waybills, false);
jasperPrint = JasperFillManager.fillReport(jasperReport, paramters, ds);
if (jasperPrint != null) {
respons.setContentType("application/octet-stream");
ServletOutputStream ouputStream = respons.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ouputStream);
oos.writeObject(jasperPrint);
oos.flush();
oos.close();
ouputStream.flush();
ouputStream.close();
}
} catch (JRException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public ElectronicPrintService getElectronicPrintService() {
return electronicPrintService;
}
public void setElectronicPrintService(
ElectronicPrintService electronicPrintService) {
this.electronicPrintService = electronicPrintService;
}
public String[] getHawbs() {
return hawbs;
}
public void setHawbs(String[] hawbs) {
this.hawbs = hawbs;
}
}
特别提醒:JRPrintApplet.class应该放在applet目录下,因为applet是无法直接访问WEB-INF下的。
使用的jar如下(可能有些没用,但是我项目少包的话总是跑不起来,可能不是applet的问题,不过还是全部贴出来):
打印结果如下: