最近有个需求,要支持批量打印用户订单部分信息,考虑个技术方案如下

定义一个freemaker模板,把订单信息放到freemaker模板里,然后通过freemaker把数据合并成一个html字符串,然后通过itext把html信息转成对应的pdf

1引入POM

    <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-xtra</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.itextpdf.tool</groupId><artifactId>xmlworker</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.2</version></dependency><!-- freemarker engine --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.27-incubating</version></dependency>

2 freemakerUtil

这个里加载模板文件有3种,看https://blog.csdn.net/qq_33442546/article/details/52609758


import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.util.*;public class FreemarkerUtil {private static final Logger logger = LoggerFactory.getLogger(FreemarkerUtil.class);/*** freemarker config*/private static Configuration freemarkerConfig = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);static{String templatePath = Thread.currentThread().getContextClassLoader().getResource("").getPath();int wei = templatePath.lastIndexOf("WEB-INF/classes/");if (wei > -1) {templatePath = templatePath.substring(0, wei);}try {freemarkerConfig.setDirectoryForTemplateLoading(new File(templatePath, "templates/freemaker"));freemarkerConfig.setNumberFormat("#");freemarkerConfig.setClassicCompatible(true);freemarkerConfig.setDefaultEncoding("UTF-8");freemarkerConfig.setLocale(Locale.CHINA);freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);} catch (IOException e) {logger.error(e.getMessage(), e);}}/*** process Template Into String** @param template* @param model* @return* @throws IOException* @throws TemplateException*/public static String processTemplateIntoString(Template template, Object model)throws IOException, TemplateException {StringWriter result = new StringWriter();template.process(model, result);return result.toString();}/*** process String** @param templateName* @param params* @return* @throws IOException* @throws TemplateException*/public static String processString(String templateName, Map<String, Object> params)throws IOException, TemplateException {Template template = freemarkerConfig.getTemplate(templateName);String htmlText = processTemplateIntoString(template, params);return htmlText;}public static String getTestData() throws Exception{OrderPrintInfo orderPrintInfo=new OrderPrintInfo();orderPrintInfo.setOrderId(555L);orderPrintInfo.setAddress("北京市区");orderPrintInfo.setCustomerName("小辣椒");orderPrintInfo.setPhone("22222");OrderSkuInfo orderSkuInfo1 =new OrderSkuInfo();orderSkuInfo1.setName("one phone");orderSkuInfo1.setSize("1");orderSkuInfo1.setColor("1 color");orderSkuInfo1.setProductId(22222L);orderSkuInfo1.setNum(8);orderSkuInfo1.setSingleShouldPrice(new BigDecimal(22));orderSkuInfo1.setSubtotalPrice(new BigDecimal(22));orderSkuInfo1.setImgPath("222");OrderSkuInfo orderSkuInfo2 =new OrderSkuInfo();orderSkuInfo2.setName("two phone");orderSkuInfo2.setSize("2");orderSkuInfo2.setColor("2 color");orderSkuInfo2.setNum(9);orderSkuInfo2.setProductId(123455L);orderSkuInfo2.setSingleShouldPrice(new BigDecimal(233));orderSkuInfo2.setSubtotalPrice(new BigDecimal(22));orderSkuInfo2.setImgPath("333");List<OrderSkuInfo> orderSkuInfos=new ArrayList<OrderSkuInfo>();orderSkuInfos.add(orderSkuInfo1);orderSkuInfos.add(orderSkuInfo2);orderPrintInfo.setOrderSkuInfos(orderSkuInfos);// code genareteMap<String, Object> params = new HashMap<String, Object>();params.put("orderPrintInfo", orderPrintInfo);return FreemarkerUtil.processString("/printorderdetail.ftl", params);}public static void main(String args[]){
//        // parse table
//        ClassInfo classInfo=new ClassInfo();
//        classInfo.setClassComment("ProductInfoComment");
//        classInfo.setClassName("ProductInfoClass");
//        classInfo.setTableName("ProductInfoTable");OrderPrintInfo orderPrintInfo=new OrderPrintInfo();orderPrintInfo.setOrderId(555L);orderPrintInfo.setAddress("北京市区");orderPrintInfo.setCustomerName("小辣椒");orderPrintInfo.setPhone("22222");OrderSkuInfo orderSkuInfo1 =new OrderSkuInfo();orderSkuInfo1.setName("one phone");orderSkuInfo1.setSize("1");orderSkuInfo1.setColor("1 color");orderSkuInfo1.setProductId(22222L);orderSkuInfo1.setNum(8);orderSkuInfo1.setSingleShouldPrice(new BigDecimal(22));orderSkuInfo1.setSubtotalPrice(new BigDecimal(22));orderSkuInfo1.setImgPath("222");OrderSkuInfo orderSkuInfo2 =new OrderSkuInfo();orderSkuInfo2.setName("two phone");orderSkuInfo2.setSize("2");orderSkuInfo2.setColor("2 color");orderSkuInfo2.setNum(9);orderSkuInfo2.setProductId(123455L);orderSkuInfo2.setSingleShouldPrice(new BigDecimal(233));orderSkuInfo2.setSubtotalPrice(new BigDecimal(22));orderSkuInfo2.setImgPath("333");List<OrderSkuInfo> orderSkuInfos=new ArrayList<OrderSkuInfo>();orderSkuInfos.add(orderSkuInfo1);orderSkuInfos.add(orderSkuInfo2);orderPrintInfo.setOrderSkuInfos(orderSkuInfos);// code genareteMap<String, Object> params = new HashMap<String, Object>();params.put("orderPrintInfo", orderPrintInfo);try{System.out.println(FreemarkerUtil.processString("/printorderdetail.ftl", params));}catch (Exception e){e.printStackTrace();}}}

3PDF

   public static Font getChineseFont() {BaseFont bfChinese;Font fontChinese = null;try {bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// fontChinese = new Font(bfChinese, 12, Font.NORMAL);fontChinese = new Font(bfChinese, 12, Font.NORMAL, BaseColor.BLUE);} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return fontChinese;}public static void main(String[] args) {Rectangle tRectangle = new Rectangle(PageSize.A4); // 页面大小// tRectangle = new Rectangle(0, 0, 800, 600);tRectangle.setBackgroundColor(BaseColor.ORANGE); // 页面背景色tRectangle.setBorder(1220);// 边框tRectangle.setBorderColor(BaseColor.BLUE);// 边框颜色tRectangle.setBorderWidth(244.2f);// 边框宽度Document document = new Document(tRectangle);document = new Document(tRectangle.rotate());// 横向打印try {PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("HelloWorld124.pdf"));// 2-PDF文档属性document.addTitle("33");// 标题document.addAuthor("22");// 作者document.addSubject("33");// 主题document.addKeywords("nice");// 关键字document.addCreator("33");// 谁创建的// 3-综合属性:document.setMargins(10, 20, 30, 40);// 页边空白document.open();//document.add(new Chunk("今天晚上我要中大奖了:明天我就不用来公司了啊哈哈哈哈 ", getChineseFont()));// document.add(new Chunk("带着钱我要去新西兰了呀,啦啦啦啦: ", getChineseFont()));writer.setPageEmpty(true);// fasle-显示空内容的页;true-不会显示// 1-Chunk块对象: a String, a Font, and some attributes
//            document.add(new Chunk("太高兴了: ", getChineseFont()));
//
//            Chunk tChunk2 = new Chunk("中大奖", getChineseFont());
//            tChunk2.setBackground(BaseColor.CYAN, 1f, 0.5f, 1f, 1.5f); // 设置背景色
//            tChunk2.setTextRise(6); // 上浮
//            tChunk2.setUnderline(0.2f, -2f); // 下划线
//            document.add(tChunk2);
//
//            document.add(Chunk.NEWLINE); // 新建一行
//            // document.add(new Phrase("Phrase page  :")); //会上浮,不知道原因??
//
//            // 2-Phrase短语对象: a List of Chunks with leading
//            document.add(new Phrase("Phrase page  :"));//            Phrase tPhrase = new Phrase();
//            Chunk name = new Chunk("China");
//            name.setUnderline(0.2f, -2f);
//            tPhrase.add(name);
//            tPhrase.add(Chunk.NEWLINE);// 放在容器中好用
//            tPhrase.add(new Chunk("换行了 :", getChineseFont()));
//            tPhrase.add(new Chunk("chinese"));
//            tPhrase.setLeading(14f);// 行间距
//            document.add(tPhrase);
//
//            // 这边就好用,上面是Chunk,就不好用
//            // 放在段落或短语中又好用
//            document.add(Chunk.NEWLINE);//            Phrase director2 = new Phrase();
//            Chunk name2 = new Chunk("换行了---Japan", getChineseFont());
//            name2.setUnderline(0.2f, -2f);
//            director2.add(name2);
//            director2.add(new Chunk(","));
//            director2.add(new Chunk(" "));
//            director2.add(new Chunk("japanese上浮下", getChineseFont()).setTextRise(3f));
//            director2.setLeading(24);
//            document.add(director2);// 3-Paragraph段落对象: a Phrase with extra properties and a newline
//            document.add(new Paragraph("Paragraph page"));
//            Paragraph info = new Paragraph();
//            info.add(new Chunk("China "));
//            info.add(new Chunk("chinese"));
//            info.add(Chunk.NEWLINE); // 好用的
//            info.add(new Phrase("Japan "));
//            info.add(new Phrase("japanese"));
//            info.setSpacingAfter(10f);// 设置段落下空白// document.add(info);XMLWorkerHelper.getInstance().parseXHtml(writer, document,new ByteArrayInputStream(FreemarkerUtil.getTestData().getBytes("Utf-8")),Charset.forName("UTF-8"));document.newPage();XMLWorkerHelper.getInstance().parseXHtml(writer, document,new ByteArrayInputStream(FreemarkerUtil.getTestData().getBytes("Utf-8")),Charset.forName("UTF-8"));// 段落是比较好用的
//            Paragraph tParagraph = new Paragraph(FreemarkerUtil.getTestData(), getChineseFont());
//            tParagraph.setAlignment(Element.ALIGN_JUSTIFIED);// 对齐方式
//
//            tParagraph.setIndentationLeft(12);// 左缩进
//            tParagraph.setIndentationRight(12);// 右缩进
//            tParagraph.setFirstLineIndent(24);// 首行缩进
//
//            tParagraph.setLeading(20f);// 行间距
//            tParagraph.setSpacingBefore(5f);// 设置上空白
//            tParagraph.setSpacingAfter(10f);// 设置段落下空白
//            document.add(tParagraph);//            // 每个新的段落会另起一行
//            tParagraph = new Paragraph("新的段落", getChineseFont());
//            tParagraph.setAlignment(Element.ALIGN_CENTER);// 居中
//            document.add(tParagraph);document.close();writer.close();} catch (Exception e) {e.printStackTrace();}}

freemaker模板文件

<!DOCTYPE html>
<html>
<head><meta charset="utf-8" /><meta name="keywords" content="" /><meta name="description" content="" /><title>$!printText.title</title><link type="text/css" rel="stylesheet" href="../css/print.css" source="combo" />
</head>
<body style = "font-family: SimSun;">
<div id="printDiv"><div class="header"><div class="w"><a href="javascript:;" class="logo"><img src="../img/logo.png" alt="" /></a></div></div><div class="w"><div class="shop-list"><ul><li><div class="cell">${orderPrintInfo.orderId}</div> </li><li><div class="cell">${orderPrintInfo.customerName}</div> </li><li><div class="cell">${orderPrintInfo.phone}</div> </li><li><div class="cell">${orderPrintInfo.address}</div> </li></ul></div><div class="shop-detail"><table cellpadding="0" cellspacing="0" width="100%"><tbody><tr><th>ProductID</th><th class="align-right">NUM</th><th class="align-right">price</th><th class="align-right">All Price</th></tr><#list orderPrintInfo.orderSkuInfos as c><tr><td class="align-left"><div class="s-img">${c.imgPath}</div><div class="s-detail"><div class="s-title">${c.name}</div><div class="s-info">${c.size}</div></div></td><td>${c.productId}</td><td class="align-right">${c.num}</td><td class="align-right">${c.singleShouldPrice}</td><td class="align-right">${c.subtotalPrice}</td></tr></#list></tbody></table></div></div>
</div></body>
</html>

题外话:如果想把配置文件放到一个xml里,然后xml增加别的信息可以先解析xml(使用Jaxb2.0实现XML<->Java Object的Mapper)然后在把对应配置文件元数据拿出来通过freemaker来生成对应的文件.

批量打印订单的技术方案相关推荐

  1. 微信小商店如何自动手动批量打印订单小票、商品标签、发货单、销售单、配货单、电子面单?

    微信小商店是微信官方推出的一款免费的商城小程序,但是功能不是特别丰富,例如无法自动打印新订单.因为对于很多餐饮.零售.配送等商家来说,能自动打印新订单将免去商家查看手机.电脑,并且便于配货送货等.还有 ...

  2. 计算机怎么打印订单,微信小商店怎么打印订单小票、标签、发货单、电子面单?...

    微信小商店是微信官方推出的一款免费的商城小程序,但是功能不是特别丰富,例如无法自动打印新订单.因为对于很多餐饮.零售.配送等商家来说,能自动打印新订单将免去商家查看手机.电脑,并且便于配货送货等.还有 ...

  3. 归因组件ACE:订单归类技术解决方案

    前言 天猫优品导购归因链路负责天猫优品订单导购判定工作,目前支撑了天猫优品权益券导购.普通导购和淘花导购等多种导购类型.随着业务迭代,现有导购归因链路在维护性.扩展性和可读性等方面存在明显不足,代码复 ...

  4. 每日百万订单,这样的技术方案更靠谱

    大家好,我是涛哥. 前段时间发了一篇原创文章"日订单量达到100万单后,我们做了订单中心重构",得到了不少读者的好评,也被不少公众号转发了30多次.根据读者反馈,我对本文做了部分优 ...

  5. access如何保存小数点后_条码标签打印软件如何批量制作订单标签

    在生活中我们定外卖,商家收到订单,打印出来订单标签,方便配货,也有工厂收到订单后打印出订单标签,工人根据订单标签的内容进行配货发货,那么如何批量制作订单标签呢?今天用条码标签打印软件给大家演示批量制作 ...

  6. python批量打印复印_惠普集群打印 小规模灵活批量打印方案

    在我们的日常工作中有一种叫"小批量打印",例如操作手册.广告宣传等. 惠普解决方案集群打印技术集计算机.网络和分布技术于一身,将多台惠普激光打印机组成一台虚拟超高速打印机,打印速度 ...

  7. netty 游戏服务器框图_基于Netty和WebSocket协议实现Web端自动打印订单服务方法与流程...

    本发明涉及电子商务技术领域,尤其涉及一种基于netty和websocket协议实现web端自动打印订单服务方法. 背景技术: 电子商务是以信息网络技术为手段,以商品交换为中心的商务活动:也可理解为在互 ...

  8. python 批量打印文档_使用python将Excel数据填充Word模板并生成Word

    [项目需求] Excel中有一万多条学生学平险数据,需要给每位学生打印购买回执单,回执单包括学生姓名,身份证号,学校等信息,目前只能从Excel拷贝数据到Word模板中,然后打印,效率及其低下,寻求帮 ...

  9. 快递电子面单批量打印接口对接demo-JAVA

    目前有三种方式对接电子面单: 1.快递公司:各家快递公司逐一对接接口 2.菜鸟:支持常用15家快递电子面单打印 3.快递鸟:仅对接一次,支持常用30多家主流快递电子面单打印 目前也是支持批量打印电子面 ...

最新文章

  1. js简单的设置快捷键,hotkeys捕获键盘键和组合键的输入
  2. 5 篇 AAAI 2018 论文看「应答生成」
  3. 值类型和引用类型的区别
  4. C#中的System.Speech命名空间初探
  5. [转载] python iter( )函数
  6. 孙鑫MFC笔记之十二--网络编程
  7. 7 Web前端性能优化
  8. Delphi版 熊猫烧香源码
  9. Windows10鼠标光标及浏览器点击效果【win10美化】
  10. 华硕笔记本U盘重装系统教程
  11. 提高数据存储效率的七个技巧
  12. NOI / 1.5编程基础之循环控制——01:求平均年龄
  13. Processing 案例 | 诡异的八爪鱼
  14. 最后完美解决pip没法用的问题
  15. java小项目家庭记账程序
  16. 计算机网络布线教学,计算机网络综合布线【基于项目的《网络综合布线》课程理实一体化教学思考】...
  17. 统计学系列:统计、数据与思想
  18. 浅谈STP中的那些事儿
  19. Oracle去重函数distinct
  20. 配置案例丨Modbus转Profinet网关连接丹佛斯变频器

热门文章

  1. java常见的查找算法
  2. html导出excel 隐藏部分,html导出Excel方法
  3. 卸载“趋势科技防毒墙网络版客户机”方法之一
  4. 利用MsChart控件绘制多曲线图表 z
  5. 雀巢普瑞纳亮相亚宠展,加码在华宠物护理业务
  6. 【MyBatis】foreach实现postgresql的json类型数据的集合包含遍历查询
  7. UDS服务基础篇之22
  8. 恢复报错ora-01180
  9. Capsule Networks 胶囊网络
  10. ORB-SLAM3中遇到的坑