itextpdf结合jfinal模版生成pdf文件


jar使用的是红色部分两个,其他的是其他的增强jar,暂时没有用到  

<!--生成pdf--> <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.11</version> </dependency> <!-- https://mvnrepository.com/artifact/com.itextpdf.tool/xmlworker iText-Html渲染--> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.5.11</version> </dependency> <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker 5.iText-Html-Freemarker渲染--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.19</version> </dependency> <!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf 6.Flying Saucer-CSS高级特性支持--> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf-itext5 6.Flying Saucer-CSS高级特性支持--> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext5</artifactId> <version>9.1.5</version> </dependency> <!--pdf转jpg --> <!-- https://mvnrepository.com/artifact/org.jpedal/jpedal-lgpl --> <!--<dependency> <groupId>org.jpedal</groupId> <artifactId>jpedal-lgpl</artifactId> <version>4.74b27</version> </dependency>--> <!--<dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>--> <!-- https://mvnrepository.com/artifact/com.lowagie/itext --> <!--<dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency>--> <!-- https://mvnrepository.com/artifact/org.apache.velocity/velocity --> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <!--生成pdf-->

 

工具的结构

 

这个结构可以适用于不同的使用方式,这里我写了三种,后续有,还可以继承抽象类就可以了,下边把代码贴出来,可以参考看一下

1.接口

import java.io.OutputStream;
import java.util.Map;

/**
 * 生成pdf的接口
 * 生成pdf都需要把一个字符串写成pdf文件输出到指定的地方
 */
public interface PDF {

    boolean writeToPDF(Map<String, Object> data, String htmlTmp, OutputStream out);
}

2.抽象类

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.jfinal.kit.PathKit;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Map;

public abstract class BasePDF implements PDF {
    //字体
    private static String FONT = PathKit.getWebRootPath() + "/js/font/simhei.ttf";

    /**
     * 字体这里设置了默认的,如果使用其他字体需要倒入字体,然后通过这个方法设定字体
     * @param FONT
     */
    public static void setFont(String FONT) {
        BasePDF.FONT = FONT;
    }

    @Override
    public boolean writeToPDF(Map<String, Object> data, String htmlTmp, OutputStream out) {
        String content = templateToString(data, htmlTmp);
        return write(content, out);
    }

    /**
     * 准备生成pdf
     */
    public boolean write(String content, OutputStream out) {
        // step 1
        Document document = new Document();
        // step 2
        PdfWriter writer = null;
        try {
            writer = PdfWriter.getInstance(document, out);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        // step 3
        document.open();
        // step 4
        XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
        fontImp.register(FONT);
        try {
            XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                    new ByteArrayInputStream(content.getBytes()), null, Charset.forName("UTF-8"), fontImp);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        // step 5
        document.close();
        return true;
    }

    /**
     * 要输出的字符串模板
     */
    public abstract String templateToString(Map<String, Object> data, String htmlTmp);
}

3.jfinal实现类

import com.jfinal.template.Engine;
import com.jfinal.template.Template;

import java.util.Map;

public class TemplateToPDFJfinal extends BasePDF {
    protected static Engine myEngine;

    /**
     * 系统启动时初始化,在启动文件中的设置
     */
    public static void setEngine(Engine engine) {
        TemplateToPDFJfinal.myEngine = engine;
    }

    public static Engine getEngine() {
        return myEngine;
    }

    @Override
    public String templateToString(Map<String, Object> data, String htmlTmp) {
        if(myEngine == null){
            throw new RuntimeException("Did not setEngine(Engine engine),You must setEngine(Engine engine) after using this tool");
        }
        
        myEngine.setDevMode(true);
        myEngine.setEncoding("UTF-8");
        Template template = myEngine.getTemplate(htmlTmp);
        return template.renderToString(data);
    }
}

4.代理类

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class PDFProxy<T> {
    T target;

    public PDFProxy(T target) {
        this.target = target;
    }

    public Object getInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getSuperclass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object invoke = method.invoke(target, args);
                        return invoke;
                    }
                });
    }
}

5.工厂类

public class PDFFactory {
    public static PDF getPDF(Class<?> p) {
        PDF pdf = null;
        try {
            pdf = (PDF) p.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        PDFProxy pdfProxy = new PDFProxy(pdf);
        return (PDF) pdfProxy.getInstance();
    }
}

6.数据封装类

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.Map;

public class pdfTest {
    public static final String DESTJfinal = "/pdfJfinal.pdf";

    /**
     * 简单写个方法测试 生成pdf
     *
     * @param templateName 模板名称位置
     * @param outPath      输出位置
     * @param pdfClass     使用的是哪个实现类
     */
    public static void test(String templateName, String outPath, Class<?> pdfClass) {
        //设置字体
        //BasePDF.setFont("/xx/xx.ttf");

        PDF pdf = PDFFactory.getPDF(pdfClass);
        Map<String, Object> m = new HashMap<>();
        m.put("red", "红色");
        try {
            pdf.writeToPDF(m, templateName, new FileOutputStream(new File(outPath)));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

7.使用

 /**
     * 测试报告使用
     * 生成这一周的报告
     * /report/handleTestReport
     * 这个会把pdf生成到项目到根目录下,根据需求自己调
     */
    @Clear
    public void handleTestReport() {
        pdfTest.test("/mail/a.html", PathKit.getWebRootPath() + pdfTest.DESTJfinal, TemplateToPDFJfinal.class);
    }

 

好了上边是所有到类

下边把基础的辅助资料写一下

字体:我把字体放到根目录下的js下了,具体看图片,根据自己的需求,我写了设置字体的方法没,可以自己设置

模版文件:我放到了根目录下的mail下了

内容是:

<!--要求比较严格,html中的标签必须有开始结束标签, 但标签需要加 /   比如:<meta charset="UTF-8" /> -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>jfinal模板使用</title>
    <style>
        body {
       //比较重要的一点,如果这里设置的字体是我们后台设置的不一样的,是没有的字体,那么,中文就不会显示了,还有就是标签一定要按照规定写,一定要有闭合标签或者 < xxx /> 这样字的
font-family: SimHei,serif; } .pos { position: absolute; left: 200px; top: 5px; width: 200px; font-size: 10px; } .table-one { width: 700px; text-align: center; border-collapse: collapse; } /*细调试*/ .title-big{ font-size: 20px; } .title-middle{ font-size: 16px; } .title-small{ font-size: 13.33px; } .red{ background-color: #E11B22; } .black{ background-color: black; color: white; } </style> </head> <body> <div class="pos"> <!--图片--> <table class="table-one"> <tr> <td colspan="5"> <img alt="tp" style="width: 153px;margin-left: 300px" src="/Users/renjianjun/Downloads/斗图/mao.jpg"/> </td> </tr> </table> <table border="1" class="table-one"> <tr> <td colspan="5" class="title-big black">20px标题</td> </tr> <tr class="title-middle"> <td class="red" rowspan="3"> <table> <tr><td>#(red)这里是取值,为了实验没有多写,只有这三个取值</td></tr> <tr><td>#(red)</td></tr> <tr><td>#(red)</td></tr> </table> </td> <td colspan="4">数据</td> </tr> <tr class="title-middle"> <!-- <td class="red">红色</td>--> <td colspan="4">数据</td> </tr> <tr class="title-middle"> <!-- <td class="red">红色</td>--> <td colspan="4">数据</td> </tr> <tr class="title-middle black"> <td colspan="5">16px二级标题</td> </tr> <tr class="title-small"> <td>13px标题</td> <td>13px数据</td> <td>13px数据</td> <td>13px数据</td> <td>13px数据</td> </tr> <tr class="title-small"> <td>13px标题</td> <td>13px数据</td> <td>13px数据</td> <td>13px数据</td> <td>13px数据</td> </tr> <tr class="title-small"> <td>13px标题</td> <td>13px数据</td> <td colspan="2">13px数据</td> <td>13px数据</td> </tr> <tr> <td class="title-middle">16px标题</td> <td colspan="4" class="title-small">13px数据</td> </tr> <tr> <td class="title-middle">16px标题</td> <td colspan="4" class="title-small">13px数据</td> </tr> <tr> <td class="title-middle">16px标题</td> <td colspan="4" class="title-small">13px数据</td> </tr> <tr> <td class="title-middle">16px标题</td> <td colspan="4" class="title-small">13px数据</td> </tr> <tr> <td class="title-middle">16px标题</td> <td colspan="4" class="title-small">13px数据</td> </tr> </table> </div> </body> </html>

好了这个是模版的内容,下边看一下预览效果:

 可能有些地方使用了代理,又使用了工厂模式,麻烦了,但是一个是自己练手,一个是这样子扩展性还是不错的。使用起来也简单。

转载于:https://www.cnblogs.com/renjianjun/p/10939623.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值