您现在的位置是:首页 > 正文

java ftl转pdf_FreeMarker(二):利用FreeMarker转pdf

2024-02-01 03:09:18阅读 3

1. 设计需求

订票成功后,生成一个pdf 文件,用户打印入场票,门票大致如下所示:

78b3f8fdb5bad830eeaaae8f062b5bb8.png

2. 设计思想

1). 使用FreeMarker 转换 ftl(就是FreeMarker 魔板文件),生成HTML

2). 使用jtidy库将 HTML转换成 对格式要求严格的 XHTML

3 ) . 使用Itext 库将XHTML转换成PDF

3. Demo 创建

简介:本项目是在Maven 的环境中搭建的,其pom.xml 主要导入的依赖如下:

org.freemarker

freemarker

2.3.28

com.itextpdf.tool

xmlworker

5.5.6

net.sf.jtidy

jtidy

r938

3.1 FreeMarker 魔板转换成pdf 源码如下:

public class FreeMarkToHtml {

/**

* 通过路径 和文件名称后去魔板

*

* @param templateFilePath

* @param templateFileName

* @return

*/

public static Template getTemplate(String templateFilePath, String templateFileName) {

try {

Configuration cfg = new Configuration();

cfg.setClassicCompatible(true);

TemplateLoader templateLoader = new FileTemplateLoader(new File(

templateFilePath));

cfg.setTemplateLoader(templateLoader);

return cfg.getTemplate(templateFileName);

} catch (IOException e) {

e.printStackTrace();

}

return null;

}

/**

* @param templateFilePath

* @param templateFileName 加载的模板文件名

* @param replaceData

* @param outFile 生成指定文件

* @return 成功,返回文件名;失败,返回null。

*/

public static String freemarkToHtml(String templateFilePath, String templateFileName, Map replaceData,

String outFile) {

String path = null;

Writer out = null;

try {

out = new BufferedWriter(new OutputStreamWriter(

new FileOutputStream(outFile), "UTF-8"));

Template temp = getTemplate(templateFilePath, templateFileName);

temp.setEncoding("UTF-8");

temp.process(replaceData, out);

path = outFile;

} catch (IOException e) {

e.printStackTrace();

path = null;

} catch (TemplateException e) {

e.printStackTrace();

path = null;

} finally {

try {

if (out != null)

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return path;

}

}

3.1 使用jtidy库将 HTML转换成 对格式要求严格的 XHTML源码

/**

* 将html 转换成为严格的XHTML

*/

public class Html2Xhtml {

/**

* 转化类

*

* @param html html文件输入路径(带文件名称)

* @param xhtml xhtml文件输入路径(带文件名称)

* @return

*/

public static String html2Xhtml(String html, String xhtml) {

String path = null;

try {

FileInputStream fin = new FileInputStream(html);

ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();

int data = -1;

while ((data = fin.read()) != -1) {

byteArrayOut.write(data);

}

fin.close();

byte[] htmlFileData = byteArrayOut.toByteArray();

byteArrayOut.close();

ByteArrayInputStream tidyInput = new ByteArrayInputStream(

htmlFileData);

ByteArrayOutputStream tidyOut = new ByteArrayOutputStream();

Tidy tidy = new Tidy();

tidy.setInputEncoding("UTF-8");

tidy.setOutputEncoding("UTF-8");

tidy.setShowWarnings(false);

tidy.setIndentContent(true);

tidy.setSmartIndent(true);

tidy.setIndentAttributes(false);

tidy.setMakeClean(true);

tidy.setQuiet(true);

tidy.setWord2000(true);

tidy.setXHTML(true);

tidy.setErrout(new PrintWriter(System.out));

tidy.parse(tidyInput, tidyOut);

tidyInput.close();

tidyOut.writeTo(new FileOutputStream(xhtml));

tidyOut.flush();

tidyOut.close();

path = xhtml;

} catch (FileNotFoundException e) {

e.printStackTrace();

path = null;

} catch (IOException e) {

e.printStackTrace();

path = null;

}

return path;

}

}

3.3 使用Itext 库将XHTML转换成PDF

/**

* @Description: xhtml --> pdf

* @Author: liupenghao

* @Date: 2018/4/17 ❤❤ 11:16

*/

public class XHtml2Pdf {

/**

* 转化方法

*

* @param html html文件输入路径(带文件名称)

* @param pdf pdf文件输出路径(带文件名称)

*/

public static void XHtml2Pdf(String html, String pdf)

throws FileNotFoundException, IOException, DocumentException,

CssResolverException {

int i = html.lastIndexOf(".html");

String xhtml = null;

xhtml = html.substring(0, i) + ".xhtml";

xhtml = Html2Xhtml.html2Xhtml(html, xhtml);

if (xhtml != null) {

Document document = new Document();

PdfWriter writer = PdfWriter.getInstance(document,

new FileOutputStream(pdf));

document.open();

FontProvider fontProvider = new FontProvider();

fontProvider.addFontSubstitute("lowagie", "garamond");

fontProvider.setUseUnicode(true);

// 使用我们的字体提供器,并将其设置为unicode字体样式

CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);

HtmlPipelineContext htmlContext = new HtmlPipelineContext(

cssAppliers);

htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

CSSResolver cssResolver = XMLWorkerHelper.getInstance()

.getDefaultCssResolver(true);

Pipeline> pipeline = new CssResolverPipeline(cssResolver,

new HtmlPipeline(htmlContext, new PdfWriterPipeline(

document, writer)));

XMLWorker worker = new XMLWorker(pipeline, true);

XMLParser p = new XMLParser(worker);

File input = new File(xhtml);

p.parse(new InputStreamReader(new FileInputStream(input), "UTF-8"));

document.close();

}

}

}

3.4 启动类编写

/**

* 描述:

*

* @author liupenghao

* @create 2018-04-17 9:58

**/

public class ApplicationStart {

public static void main(String[] args) {

URL url = Thread.currentThread().getContextClassLoader().getResource("");

Map replaceData = initData();

FreeMarkToHtml.freemarkToHtml(url.getPath(), "template.ftl", replaceData, url.getPath() + "result.html");

try {

XHtml2Pdf.XHtml2Pdf(url.getPath() + "result.html", url.getPath() + "result.pdf");

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} catch (DocumentException e) {

e.printStackTrace();

} catch (CssResolverException e) {

e.printStackTrace();

}

}

public static HashMap initData() {

HashMap needReplaceMapData = new HashMap();

/******************************************单个属性************************************/

needReplaceMapData.put("name", "刘亦菲");

/******************************************list 属性添加***********************************/

List students = new ArrayList();

for (int i = 0; i < 2; i++) {

Student student = new Student();

student.setId(i);

student.setName(" 葫芦娃" + i + "号");

students.add(student);

}

needReplaceMapData.put("students", students);

/******************************************日期 ***********************************/

needReplaceMapData.put("date", new Date());

needReplaceMapData.put("showDate", true);

needReplaceMapData.put("imgUrl", "http://n.sinaimg.cn/translate/344/w700h1244/20180410/B_F_-fyzeyqa1740187.jpg");

needReplaceMapData.put("description", "描述 一只猫");

return needReplaceMapData;

}

}

3.5 中文乱码的解决

/**

* @Description: 字体提供类, 更改 默认的字体

* @Author: liupenghao

* @Date: 2018/4/17 ❤❤ 11:19

*/

public class FontProvider extends XMLWorkerFontProvider {

public FontProvider() {

super(null, null);

}

@Override

public Font getFont(final String fontname, String encoding, float size,

final int style) {

String fntname = fontname;

if (fntname == null) {

fntname = "宋体";

}

return super.getFont(fntname, encoding, size, style);

}

}

4. 项目源码:

网站文章

  • BootStrap 多个tab页面 保存提交后停留在操作tab页或者指定tab页

    jQ+ Bootstrap 动态控制tab页面切换最近在做一个功能,一个页面包含多个tab页签,每一个tab页面都有保存和提交按钮功能,现在是希望在某个tab页面点击保存或者提交按钮提交表单后,重新加...

    2024-02-01 03:09:11
  • 手把手教你搭建自己的git+gerrit代码评审服务器

    手把手教你搭建自己的git+gerrit代码评审服务器

    你可能遇到过这样的问题,不知道如何管理自己的代码。自己开发的代码,过了几天,忘记修改了什么,忘了上次改到哪了,代码突然找不到了等等,甚至容易消磨自己的耐心,成就感不高。今天就教你用git+gerrit...

    2024-02-01 03:09:04
  • 每日面试题(三)----深拷贝

    每日面试题(三)----深拷贝

    深拷贝与浅拷贝

    2024-02-01 03:08:35
  • 离线安装docker

    离线安装docker

    在/usr/lib/systemd/system/目录下,创建docker.service文件:sudo touch /usr/lib/systemd/system/docker.service。编辑...

    2024-02-01 03:08:19
  • java数据结构和算法

    java数据结构和算法

    java数据结构与算法

    2024-02-01 03:08:11
  • 多标签mAP解释和计算

    多标签mAP计算

    2024-02-01 03:08:04
  • 【VMware】VMware 虚拟机使用笔记

    【VMware】VMware 虚拟机使用笔记

    目录 共享文件夹配置 VMware问题记录 VMware安装出错error 1021 Vmware虚拟机Ubuntu未发现WiFi适配器解决方案汇总 添加域名解析服务器 虚拟机没有网络(不显示网络图标)解决方法 虚拟机添加新硬盘的方法 共享文件夹配置 在vmware上操作: 1.1打开 虚拟机 --> 设置 1.2在 「虚拟...

    2024-02-01 03:07:35
  • mysql 全文检索 demo

    mysql 全文检索 demo

    mysql5.6.7之后开始支持中文全文检索 模拟插入点数据,是的 存储过程。

    2024-02-01 03:07:29
  • [033] 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    [033] 微信公众帐号开发教程第9篇-QQ表情的发送与接收

    我想大家对QQ表情一定不会陌生,一个个小头像极大丰富了聊天的乐趣,使得聊天不再是简单的文字叙述,还能够配上喜、怒、哀、乐等表达人物心情的小图片。本文重点要介绍的内容就是如何在微信公众平台使用QQ表情,即在微信公众帐号开发模式下,如何发送QQ表情给用户,以及如何识别用户发来的是QQ表情。 QQ表情代码表 首先需要明确的是:QQ表情虽然呈现为一张张动态的表情图片,但在微信公众平台的消息接口中却...

    2024-02-01 03:07:23
  • 【MySQL系列】 MySQL表的增删改查(进阶)

    【MySQL系列】 MySQL表的增删改查(进阶)

    MySQL表的增删改查的进阶部分的内容~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    2024-02-01 03:06:55