java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
本篇文章主要介绍了 java 根据模板动态生成 PDF 实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
一、需求说明:
根据业务需要,需要在服务器端生成可动态配置的 PDF 文档,方便数据可视化查看。
二、解决方案:
iText+FreeMarker+JFreeChart 生成可动态配置的 PDF 文档
iText 有很强大的 PDF 处理能力,但是样式和排版不好控制,直接写 PDF 文档,数据的动态渲染很麻烦。
FreeMarker 能配置动态的 html 模板,正好解决了样式、动态渲染和排版问题。
JFreeChart 有这方便的画图 API,能画出简单的折线、柱状和饼图,基本能满足需要。
三、实现功能:
1、能动态配置 PDF 文档内容
2、能动态配置中文字体显示
3、设置自定义的页眉页脚信息
4、能动态生成业务图片
5、完成 PDF 的分页和图片的嵌入
四、主要代码结构说明:
1、component 包:PDF 生成的组件 对外提供的是 PDFKit 工具类和 HeaderFooterBuilder 接口,其中 PDFKit 负责 PDF 的生成,HeaderFooterBuilder 负责自定义页眉页脚信息。
2、builder 包:负责 PDF 模板之外的额外信息填写,这里主要是页眉页脚的定制。
3、chart 包:JFreeChart 的画图工具包,目前只有一个线形图。
4、test 包:测试工具类
5、util 包:FreeMarker 等工具类。
五、关键代码说明:
1、模板配置
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
- <meta http-equiv="Content-Style-Type" content="text/CSS"/>
- <title></title>
- <style type="text/css">
- body {
- font-family: pingfang sc light;
- }
- .center{
- text-align: center;
- width: 100%;
- }
- </style>
- </head>
- <body>
- <!--第一页开始-->
- <div class="page" >
- <div class="center"><p>${templateName}</p></div>
- <div><p>iText官网:${ITEXTUrl}</p></div>
- <div><p>FreeMarker官网:${freeMarkerUrl}</p></div>
- <div><p>JFreeChart教程:${JFreeChartUrl}</p></div>
- <div>列表值:</div>
- <div>
- <#list scores as item>
- <div><p>${item}</p></div>
- </#list>
- </div>
- </div>
- <!--第一页结束-->
- <!---分页标记-->
- <span style="page-break-after:always;"></span>
- <!--第二页开始-->
- <div class="page">
- <div>第二页开始了</div>
- <!--外部链接-->
- <p>百度图标</p>
- <div>
- <img src="${imageUrl}" alt="百度图标" width="270" height="129"/>
- </div>
- <!--动态生成的图片-->
- <p>气温变化对比图</p>
- <div>
- <img src="${picUrl}" alt="我的图片" width="500" height="270"/>
- </div>
- </div>
- <!--第二页结束-->
- </body>
- </html>
2、获取模板内容并填充数据
- /**
- * @description 获取模板
- */
- public static String getContent(String fileName, Object data) {
- String templatePath = getPDFTemplatePath(fileName); //根据PDF名称查找对应的模板名称
- String templateFileName = getTemplateName(templatePath);
- String templateFilePath = getTemplatePath(templatePath);
- if (StringUtils.isEmpty(templatePath)) {
- throw new FreeMarkerException("templatePath can not be empty!");
- }
- try {
- Configuration config = new Configuration(Configuration.VERSION_2_3_25); //FreeMarker配置
- config.setDefaultEncoding("UTF-8");
- config.setDirectoryForTemplateLoading(new File(templateFilePath)); //注意这里是模板所在文件夹,不是文件
- config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
- config.setLogTemplateExceptions(false);
- Template template = config.getTemplate(templateFileName); //根据模板名称 获取对应模板
- StringWriter writer = new StringWriter();
- template.process(data, writer); //模板和数据的匹配
- writer.flush();
- String html = writer.toString();
- return html;
- } catch(Exception ex) {
- throw new FreeMarkerException("FreeMarkerUtil process fail", ex);
- }
- }
3、导出模板到 PDF 文件
- /**
- * @description 导出pdf到文件
- * @param fileName 输出PDF文件名
- * @param data 模板所需要的数据
- *
- */
- public String exportToFile(String fileName, Object data) {
- String htmlData = FreeMarkerUtil.getContent(fileName, data); //获取FreeMarker的模板数据
- if (StringUtils.isEmpty(saveFilePath)) {
- saveFilePath = getDefaultSavePath(fileName); //设置PDF文件输出路径
- }
- File file = new File(saveFilePath);
- if (!file.getParentFile().exists()) {
- file.getParentFile().mkdirs();
- }
- FileOutputStream outputStream = null;
- try {
- //设置输出路径
- outputStream = new FileOutputStream(saveFilePath);
- //设置文档大小
- Document document = new Document(PageSize.A4); //IText新建PDF文档
- PdfWriter writer = PdfWriter.getInstance(document, outputStream); //设置文档和输出流的关系
- //设置页眉页脚
- PDFBuilder builder = new PDFBuilder(headerFooterBuilder, data);
- builder.setPresentFontSize(10);
- writer.setPageEvent(builder);
- //输出为PDF文件
- convertToPDF(writer, document, htmlData);
- } catch(Exception ex) {
- throw new PDFException("PDF export to File fail", ex);
- } finally {
- IOUtils.closeQuietly(outputStream);
- }
- return saveFilePath;
- }
4、测试工具类
- public String createPDF(Object data, String fileName) {
- //pdf保存路径
- try {
- //设置自定义PDF页眉页脚工具类
- PDFHeaderFooter headerFooter = new PDFHeaderFooter();
- PDFKit kit = new PDFKit();
- kit.setHeaderFooterBuilder(headerFooter);
- //设置输出路径
- kit.setSaveFilePath("/Users/fgm/Desktop/pdf/hello.pdf");//设置出书路径
- String saveFilePath=kit.exportToFile(fileName,data);
- return saveFilePath;
- } catch (Exception e) {
- log.error("PDF生成失败 {}
- ", ExceptionUtils.getFullStackTrace(e));
- return null;
- }
- }"
- public static void main(String[] args) {
- ReportKit360 kit = new ReportKit360();
- TemplateBO templateBO = new TemplateBO(); //配置模板数据
- templateBO.setTemplateName("Hello iText! Hello freemarker! Hello jFreeChart!");
- templateBO.setFreeMarkerUrl("http://www.zheng-hang.com/chm/freemarker2_3_24/ref_directive_if.html");
- templateBO.setITEXTUrl("http://developers.itextpdf.com/examples-itext5");
- templateBO.setJFreeChartUrl("http://www.yiibai.com/jfreechart/jfreechart_referenced_apis.html");
- templateBO.setImageUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png");
- List < String > scores = new ArrayList < String > ();
- scores.add("90");
- scores.add("95");
- scores.add("98");
- templateBO.setScores(scores);
- List < Line > lineList = getTemperatureLineList();
- TemperatureLineChart lineChart = new TemperatureLineChart();
- String picUrl = lineChart.draw(lineList, 0); //自定义的数据画图
- templateBO.setPicUrl(picUrl);
- String path = kit.createPDF(templateBO, "hello.pdf");
- System.out.println(path);
- }
六、生成效果图:
七、项目完整代码
1、github 地址: https://github.com/superad/pdf-kit
八、遇到的坑:
1、FreeMarker 配置模板文件样式,在实际 PDF 生成过程中,可能会出现一些不一致的情形,目前解决方法,就是换种方式调整样式。
2、字体文件放在 resource 下,在打包时会报错,运行 mvn -X compile 会看到详细错误:
这是字体文件是二进制的,而 maven 项目中配置了资源文件的过滤,不能识别二进制文件导致的,plugins 中增加下面这个配置就好了:
- <build>
- <resources>
- <resource>
- <directory>src/main/resources</directory>
- <filtering>true</filtering>
- </resource>
- </resources>
- <!--增加的配置,过滤ttf文件的匹配-->
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-resources-plugin</artifactId>
- <version>2.7</version>
- <configuration>
- <encoding>UTF-8</encoding>
- <nonFilteredFileExtensions>
- <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
- </nonFilteredFileExtensions>
- </configuration>
- </plugin>
- </plugins>
- </build>
3、PDF 分页配置:
来源: http://www.phperz.com/article/17/1224/357313.html