博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
多线程报表生成其中报表以pdf形式保存
阅读量:5300 次
发布时间:2019-06-14

本文共 13846 字,大约阅读时间需要 46 分钟。

     设计思路采用生产者消费者模式,生产者生产报表消费者消费报表生成pdf文件其中报表以html形式存储在线程安全列表中.使用到技术有:多线程协作,线程池,线程安全,html 生成pdf.

一.生产者生成html模版,方式通过多线程将数据和html模版整合技术是使用freemarker.

1.ValPdfProduce

package hk.buttonwood.ops.report;import java.io.File;import java.util.HashMap;import java.util.List;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import hk.buttonwood.ops.pdf.Msg;import hk.buttonwood.ops.pdf.PdfProducer;import hk.buttonwood.ops.portfolio.PortfolioService;import net.zweb.core.ioc.annotation.Inject;import net.zweb.core.ioc.annotation.Resource;import net.zweb.core.util.FileUtil;/** * @author maybo 2015年10月31日 */@Resourcepublic class ValPdfProduce {	private String root = "/home/maybo/myProject/";// 保存文件的根目录	private String tPath = "src/main/webapp/WEB-INF/templates/ops/report/cash_pdf.html";// html模版文件	public ThreadPoolExecutor producerPool;	public  PdfProducer pdfProducer;	@Inject	private PortfolioService portfolioService;// 投资组合服务用于获取所有列	private ValProducer producer;	public ThreadPoolExecutor getProducerPool() {		return this.producerPool;	}	public void setPortfolioService(PortfolioService portfolioService) {		this.portfolioService = portfolioService;	}	public ValPdfProduce(String root, String tPath, ValProducer producer) {		this.root = root;		this.tPath = tPath;		this.producer = producer;	}	public ValPdfProduce() {	}	/*	 * 生成pdf	 */	public void produce(List
portfolios,String from,String to,String root, String tPath, ValProducer producer) { this.root=root; this.tPath=tPath; this.producer=producer; int cpu = Runtime.getRuntime().availableProcessors(); Msg msg=new Msg(); //如果portfolio存在无需查询 if(portfolios==null||portfolios.size()<=0){ // 获取所有portfolio列表 portfolios = this.portfolioService.findAll(); } if (portfolios == null || portfolios.isEmpty()||portfolios.size()<=0) { Msg.State state=new Msg.State(); state.setState(Msg.State.NO_DATA); msg.add(state); msg.setTotal(-1); return; } pdfProducer = PdfProducer.newInstance(); LinkedBlockingQueue
> queue = pdfProducer.getCached(); String html = htmlToString(tPath); if (html == null || html == "") { Msg.State state=new Msg.State(); state.setState(Msg.State.NO_DATA); msg.add(state); msg.setTotal(-1); return; } msg.setTotal(portfolios.size()); pdfProducer.setMsg(msg); // 开启一个生产估值数据的线程池 producerPool = new ThreadPoolExecutor(cpu / 2, 500, 5, TimeUnit.MINUTES, new ArrayBlockingQueue
(500)); for (Integer p : portfolios) { if (p< 0) {//但没有值时返回状态 Msg.State state=new Msg.State(); state.setPortfolio(p); state.setState(Msg.State.NO_DATA); msg.add(state); continue; } producerPool.execute(new ValProduceTask( msg,queue, p,html, root, this.producer,from,to)); try { pdfProducer.addTask(null); } catch (Exception e) { e.printStackTrace(); } } try { pdfProducer.shutDown(); } catch (Exception e) { e.printStackTrace(); } producerPool.shutdown(); } /* * 将html和数据整合到一起 * * @param:html文件路径 * */ private String htmlToString(String htmlFile) { String html = ""; File file = new File(htmlFile); if (file.exists() && file.isFile()) { html = FileUtil.readFile(file); } return html; }}

 2.

package hk.buttonwood.ops.report;import java.util.Map;import hk.buttonwood.ops.pdf.ExcTask;/** * @author maybo 2015年10月31日 */public abstract class ValProducer{	/*	 * 将月结单数据保存到数据模版中	 * 	 * @param:portfolio中id	 * 	 * @param:保存文件的根目录	 * 	 * @param:htmlFile的位置	 * @param:更新日期	 */	protected abstract Map
valToPdfTemplate(int portfolio,String root, String html,String date); /* * 将月结单数据保存到数据模版中 * * @param:portfolio中id * * @param:保存文件的根目录 * * @param:htmlFile的位置 * * @param:更新日期 * @param:截至日期 */ protected abstract Map
valToPdfTemplate(int portfolio, String root, String html,String from,String to);}

  3.生产任务

package hk.buttonwood.ops.report;import java.util.HashMap;import java.util.Map;import java.util.concurrent.LinkedBlockingQueue;import hk.buttonwood.ops.pdf.Msg;/* * 建立一个获取数据的线程 *//** * @author maybo *	2015年10月31日 */public class ValProduceTask extends Thread {	// 线程安全队列用以存储数据	private LinkedBlockingQueue
> queue; private int portfolio;// 投资组合的id private String from;// 当前日期 private String html;// html模版 private String root;// 存储的根目录 private ValProducer valProducer;// 获取相应的数据 private String to;// 截至日期日期 private Msg msg;//执行状态 /* * 传递所需数据 * * @param:缓存队列 * * @param:投资组合id * * @param:查询日期 * * @param:html模版 * * @param:提供的数据获取方法有调用者实现传递 * * @param:跟目录 * * @保存文件名 */ public ValProduceTask(Msg msg,LinkedBlockingQueue
> queue, int portfolio,String html, String root, ValProducer valProducer,String from,String to) { this.queue = queue; this.from = from; this.html = html; this.to=to; this.portfolio = portfolio; this.root = root; this.valProducer = valProducer; this.msg=msg; } @Override public void run() { synchronized (queue) { Map
data; if(to==null){ data = valProducer.valToPdfTemplate(portfolio,root, html, from); }else{ data = valProducer.valToPdfTemplate(portfolio,root, html, from,to); } if (data != null) { queue.add((HashMap
) data); }else{ Msg.State state=new Msg.State(); state.setPortfolio(this.portfolio); state.setState(Msg.State.NO_DATA); msg.add(state); } queue.notifyAll(); } }}

 二.消费者也就是pdf的生产者消费html模版生成pdf.

1.底层类实现将html to pdf.

/* * To change this template, choose Tools | Templates * and open the template in the editor. */package zweb.plugins.pdf;/** * * @author john */import java.io.ByteArrayInputStream;import java.io.File;import java.io.FileOutputStream;import java.util.HashMap;import java.util.Map;import net.zweb.core.config.Config;import net.zweb.core.config.MapConfig;import net.zweb.core.util.FileUtil;import org.apache.commons.lang.StringUtils;import com.itextpdf.text.BaseColor;import com.itextpdf.text.Document;import com.itextpdf.text.Font;import com.itextpdf.text.PageSize;import com.itextpdf.text.pdf.PdfWriter;import com.itextpdf.tool.xml.XMLWorkerFontProvider;import com.itextpdf.tool.xml.XMLWorkerHelper;public class HtmlToPDF {		private HeaderFooter headerFooter = null;		public HtmlToPDF(){			}		public HtmlToPDF(HeaderFooter headerFooter){		this.headerFooter = headerFooter;	}		public String print(String html, Map
data, String path) throws Exception { try { Document document = null; if(data!=null){ Config
cfg = new MapConfig
(data); String pageSize = cfg.getString("pageSize"); String direction = cfg.getString("direction"); if(StringUtils.isBlank(pageSize)){ pageSize = "letter"; } if(StringUtils.isBlank(direction)) direction = "verticle"; if(StringUtils.equals(direction, "verticle")) document = new Document(PageSize.getRectangle(pageSize)); // 竖向打印 else document = new Document(PageSize.getRectangle(pageSize).rotate()); // 横向打印 }else{ document = new Document(PageSize.LETTER); } PdfWriter pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(path)); if (this.headerFooter != null) pdfWriter.setPageEvent(headerFooter); document.open(); document.addAuthor(String.valueOf(data.get("author"))); document.addCreator(String.valueOf(data.get("creator"))); document.addSubject(String.valueOf(data.get("subject"))); document.addCreationDate(); document.addTitle(String.valueOf(data.get("title"))); XMLWorkerHelper worker = XMLWorkerHelper.getInstance(); // worker.parseXHtml(pdfWriter, document, new StringReader(str)); worker.parseXHtml(pdfWriter, document, new ByteArrayInputStream(html.getBytes()), null, new XMLWorkerFontProvider(){ @Override public Font getFont(final String fontname, final String encoding, final boolean embedded, final float size, final int style,final BaseColor color) { String fntname = fontname; if(fntname==null){ fntname="宋体"; fntname="微软雅黑"; // fntname="uming"; } return super.getFont(fntname, encoding, size, style); } } ); // worker.parseXHtml(pdfWriter, document, new // ByteArrayInputStream(html.getBytes())); document.close(); } catch (Exception e) { throw e; } return null; } public static void main(String... args) throws Exception { String root = "src/main/webapp"; HeaderFooter headerFooter = new HeaderFooter(root); headerFooter.setPrintDirection("horizon"); headerFooter.setX(-30); headerFooter.setY(630); headerFooter.setImg("/images/print_holder.png"); HtmlToPDF toPdf = new HtmlToPDF(headerFooter); String path = "d:/testpdf3.pdf"; //String str = FileUtil.readFile(new File("src/main/webapp/WEB-INF/templates/custody/fund/voucher/print.html")); String str = FileUtil.readFile(new File("src/main/webapp/WEB-INF/templates/register/holder/print_bond.html")); Map
data = new HashMap
(); data.put("author", "author"); data.put("creator", "creator"); data.put("subject", "subject"); data.put("title", "title"); data.put("direction", "horizon"); data.put("pageSize", "A4"); toPdf.print(str, data, path); }}

  2.PdfPrint 基本执行生成pdf.

package hk.buttonwood.ops.pdf;import java.util.Map;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import net.zweb.core.mvc.template.AbstractTemplateEnginePlugin;import net.zweb.core.mvc.template.TemplateEngine;import zweb.plugins.pdf.HeaderFooter;import zweb.plugins.velocity.VelocityPlugin;public class PrintPdf implements ExcTask {	private Map
data; private static TemplateEngine engine; private HeaderFooter headerFooter; private Logger logger=LoggerFactory.getLogger(PdfTask.class); static { AbstractTemplateEnginePlugin plugin = new VelocityPlugin(); engine = plugin.templateEngine(); } public PrintPdf(Map
data,HeaderFooter headerFooter) { this.data = data; this.headerFooter=headerFooter; } @SuppressWarnings("unchecked") @Override public void excute() throws Exception { String html = ""; html = htmlToString((String) data.get("html"), (Map
) data.get("datas")); if ("".equals(html)) { return; } new BuildPdfUtil(this.headerFooter).build(html, (String) data.get("saveFile"), (Map
) data.get("datas")); logger.debug((String)data.get("saveFile")+"---------------完成"); } /* * 将html和数据整合到一起 * * @param:html文件路径 * * @param:数据模型 */ private String htmlToString(String html, Map
datas) { String htl = ""; htl = engine.render(html, datas); return htl; }}

 3.线程任务生成pdf调用PdfPrint

package hk.buttonwood.ops.pdf;import java.util.HashMap;import java.util.Map;import java.util.concurrent.LinkedBlockingQueue;import zweb.plugins.pdf.HeaderFooter;/** * @author maybo 2015年10月28日 估值报告线程任务 */public class PdfTask extends Thread {	// 线程安全队列用以存储数据	private LinkedBlockingQueue
> queue; private HeaderFooter headerFooter; private Msg msg; public PdfTask(LinkedBlockingQueue
> queue,HeaderFooter headerFooter,Msg msg) { this.queue = queue; this.headerFooter=headerFooter; this.msg=msg; } @Override public void run() { synchronized(queue){ while (queue.size() <= 0) { try { queue.wait(); } catch (InterruptedException e) { e.printStackTrace(); queue.notifyAll(); } } Map
data = queue.poll(); queue.notifyAll(); try { ExcTask excTask = new PrintPdf(data,headerFooter); excTask.excute(); Msg.State state=new Msg.State(); if(data.get("portfolio")!=null){ state.setPortfolio((Integer)data.get("portfolio")); state.setState(Msg.State.OK); msg.add(state); } } catch (Exception e1) { Msg.State state=new Msg.State(); if(data.get("portfolio")!=null){ state.setPortfolio((Integer)data.get("portfolio")); state.setState(Msg.State.ERROR); msg.add(state); } e1.printStackTrace(); } } }}

  4.PdfProducer //也就是消费者

package hk.buttonwood.ops.pdf;import java.util.HashMap;import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import zweb.plugins.pdf.HeaderFooter;public class PdfProducer {	private LinkedBlockingQueue
> queue; private ThreadPoolExecutor pool; private Msg msg; private PdfProducer() { } public static PdfProducer newInstance() { PdfProducer pdfProducer = new PdfProducer(); int cpu = Runtime.getRuntime().availableProcessors();// 获取cpu核数 pdfProducer.queue = new LinkedBlockingQueue
>();// 创建队列用于缓存任务 // 开启一个生产估值数据的线程池 pdfProducer.pool = new ThreadPoolExecutor(cpu / 2-1<=0?1:cpu/2-1, 500, 5, TimeUnit.MINUTES, new ArrayBlockingQueue
(500));// 开启线程池 return pdfProducer; } public LinkedBlockingQueue
> getCached() { return queue; } public void setMsg(Msg msg) { this.msg = msg;} public Msg getMsg() { return this.msg; } // 关闭线程池 public void shutDown() { this.pool.shutdown(); } // 现在关闭 public void shutDownNow() { this.pool.shutdownNow(); } // 关闭状态 public boolean isShutDown() { return this.pool.isShutdown(); } // 是否完成任务 public boolean isTerminated() { return this.pool.isTerminated(); } public boolean isTerminating() { return this.pool.isTerminating(); } /* * 添加任务数 * param:pdf的页眉 */ public void addTask(HeaderFooter footer) throws Exception { if (this.isShutDown()) { throw new Exception("已经关闭任务."); } pool.execute(new PdfTask(queue,footer,msg)); }}

  

转载于:https://www.cnblogs.com/maybo/p/5182528.html

你可能感兴趣的文章
Vue 模板解释
查看>>
http://www.bootcss.com/
查看>>
20145308 《网络对抗》 注入shellcode+Return-to-libc攻击 学习总结
查看>>
将多张图片和文字合成一张图片
查看>>
自己动手写ORM(01):解析表达式树生成Sql碎片
查看>>
如何使用USBWebserver在本机快速建立网站测试环境
查看>>
百度Ueditor编辑器的Html模式自动替换样式的解决方法
查看>>
变量提升
查看>>
线性表可用顺序表或链表存储的优缺点
查看>>
在现有的mysql主从基础上,搭建mycat实现数据的读写分离
查看>>
[Flex] flex手机项目如何限制横竖屏?只允许横屏?
查看>>
tensorflow的graph和session
查看>>
JavaScript动画打开半透明提示层
查看>>
Mybatis生成resulteMap时的注意事项
查看>>
jquery-jqzoom 插件 用例
查看>>
1007. Maximum Subsequence Sum (25)
查看>>
iframe的父子层跨域 用了百度的postMessage()方法
查看>>
图片生成缩略图
查看>>
动态规划 例子与复杂度
查看>>
查看oracle数据库的连接数以及用户
查看>>