批量打印订单的技术方案

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

 定义一个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 genarete
        Map<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 genarete
        Map<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来生成对应的文件.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值