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>
好了这个是模版的内容,下边看一下预览效果:
可能有些地方使用了代理,又使用了工厂模式,麻烦了,但是一个是自己练手,一个是这样子扩展性还是不错的。使用起来也简单。