Jasperreport+applet实现客户端打印

需求:Web应用中,在客户端实现打印功能

可能遇到的问题:

[list]
[*][b]64bit系统装64bit的jre但是不好使[/b]
[*]装32bit的jre就好了
[*][b]打印时出现invalid header[/b]
[*]有可能是编译文件时的Jasperreport的jar版本和运行时的不一样
[*][b]打印出出现“attribute 'uuid' is not allowed to appear in element 'jasperreport'”[/b]
[*]打开JRXML文件,用正则表达式搜索uuid="\w*-\w*-\w*-\w*-\w*",全部删除
[*][b]applet访问权限受限[/b]
[*]在jre的lib\security\java.policy中的grant {...}代码块中增加
permission java.security.AllPermission;
permission java.net.SocketPermission "*", "accept, connect, listen, resolve";
[/list]

思路:

[list]
[*]利用iReport制作模版
[*]写后台代码,得到JasperPrint并输出到Servlet的流中
[*]用applet接受流,并调用打印机打印
[/list]

使用的框架、设备、环境:

[list]
[*]Spring MVC
[*]Spring Tool Suite(Eclipse系列的,Eclipse穿了个马甲)
[*]打印机EPSON LQ-630K
[/list]

资源:

[list]

[*]报表设计软件,用于制作模版,我使用的是iReport-5.0.0-windows-installer
[url]http://sourceforge.net/projects/ireport/files/iReport/iReport-5.0.0/[/url]
[*]EPSON LQ-630K驱动[url]http://epson.com.cn/[/url]

[/list]

正文:

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 制作模版

[list]

[*]首先安装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目录中

[/list]

2. 准备打印机

[list]

[*]安装驱动

[/list]

3. 使用applet打印

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

[b]注意:这个类一定要放在工程的根目录,也就是不存在任何包中,虽然有点不科学,但是在调用的时候如果有包路径是不好使的[/b]

[*] 写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放在同样的文件夹中
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值