使用Spring Boot集成thymeleaf动态生成PDF文档

Thymeleaf企业级真实应用:将HTML界面数据转换为PDF输出 Thymeleaf是一种现代化的服务器端Java模板引擎可以用于Web和独立环境中的HTML、XML、JavaScript、CSS和文本。在实际开发中,Thymeleaf可以用于生成动态的HTML页面,支持将数据与模板进行绑定,生成最终的HTML内容。它是一个开源的软件,采用Apache许可证2.0进行发布。 阅读详情

在现代Web应用中,生成PDF文档是一项常见的需求。本文将介绍如何使用Spring Boot与thymeleaf和iText库生成PDF文档,并展示如何在控制器中处理请求和异常。

依赖配置

首先,我们需要在pom.xml中添加必要的依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>html2pdf</artifactId>
        <version>2.0.2</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>kernel</artifactId>
        <version>7.1.2</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>font-asian</artifactId>
        <version>7.1.2</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
</dependencies>

定义常量

public class ExamConstant {
    public static final String TYPEFACE = "fonts/simhei.ttf";
    public static final String VARIABLE = "examData";
    public static final String FILENAME = "exam.html";
    public static final String TEMPLATE = "模板名称-自定义";
}

PDF配置

接下来,我们需要配置PDF生成的相关信息。在PdfConfiguration类中,我们定义了字体提供者和转换器属性。

注意:这里有一个坑,输出后的PDF中,除了英文数字符号,剩下的中文字符全部不显示,需在项目跟路径:src/main/resources/fonts导入字体格式。

@Configuration
public class PdfConfiguration {

    private static final Logger log = LoggerFactory.getLogger(PdfConfiguration.class);

    @Value("${pdf.pdfUrl}")
    private String pdfUrl;

    @Bean
    public FontProvider getFontProvider() throws IOException {
        FontProvider provider = new DefaultFontProvider(true, true, false);
        try (InputStream in = PrintPdfController.class.getClassLoader().getResourceAsStream(ExamConstant.TYPEFACE)) {
            if (in == null) {
                throw new IOException("Font file not found: fonts/simhei.ttf");
            }
            PdfFont pdfFont = PdfFontFactory.createFont(ExamConstant.TYPEFACE, PdfEncodings.IDENTITY_H, true);
            provider.addFont(pdfFont.getFontProgram());
        }
        return provider;
    }

    @Bean
    public ConverterProperties converterProperties(FontProvider fontProvider) {
        ConverterProperties cp = new ConverterProperties();
        cp.setBaseUri(pdfUrl);
        cp.setFontProvider(fontProvider);
        return cp;
    }
}

控制器实现

接下来,我们创建一个控制器来处理PDF打印请求。在PrintPdfController中,我们定义了printExam方法,用于接收请求参数并生成PDF。

@Controller
@RequestMapping("print")
public class PrintPdfController {

    private static final Logger log = LoggerFactory.getLogger(PrintPdfController.class);

    @Autowired
    private PrintPdfService service;

    @GetMapping("/printExam.pdf")
    public void printExam(@RequestParam String name, @RequestParam String identity, HttpServletResponse resp) throws IOException {
        try {
            service.printExam(name, identity, resp);
            if (resp.getStatus() == HttpServletResponse.SC_OK) {
                log.info("打印考试信息成功: 姓名={}, 身份证={}", name, identity);
            }
        } catch (Exception e) {
            log.error("打印考试信息失败: 姓名={}, 身份证={}, 错误={}", name, identity, e.getMessage());
            resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            resp.getWriter().write("打印考试信息时发生错误,请稍后再试。");
        }
    }
}

错误处理

printExam方法中,我们进行了参数校验和异常处理:

public void printExam(String name, String identity, HttpServletResponse resp) {
    if (name == null || name.isEmpty() || identity == null || identity.isEmpty()) {
        log.warn("打印考试信息失败:姓名或身份证号为空");
        try {
            resp.sendError(HttpServletResponse.SC_BAD_REQUEST, "姓名或身份证号不能为空");
        } catch (IOException e) {
            log.error("发送错误响应失败:{}", e.getMessage(), e);
        }
        return;
    }

    /**
    *获取自己数据库信息
    **/
    ZrcExamdemo one = service.getOne(new LambdaQueryWrapper<ZrcExamdemo>()
            .eq(ZrcExamdemo::getName, name)
            .eq(ZrcExamdemo::getIdentity, identity));

    if (one == null) {
        log.warn("订单信息不存在:姓名={}, 身份证号={}", name, identity);
        try {
            resp.sendError(HttpServletResponse.SC_NOT_FOUND, "订单信息不存在");
        } catch (IOException e) {
            log.error("发送错误响应失败:{}", e.getMessage(), e);
        }
        return;
    }

    Context context = new Context();
    context.setVariable(ExamConstant.VARIABLE, one);
    processPdf(context, ExamConstant.FILENAME, ExamConstant.TEMPLATE, resp);
}

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"/>
  <title>准考证</title>
  <style>
    body {
      font-family: SimHei;
      margin: 0;
      padding: 20px;
    }
    .container {
      max-width: 800px; /* 最大宽度为800px */
      margin: 0 auto; /* 水平居中 */
      border: 1px solid black;
      text-align: center;
    }
    table {
      width: 100%;
      border-collapse: collapse;
      margin-top: 30px;
    }
    th, td {
      padding: 10px;
      border: 1px solid black;
      text-align: center; /* 内容居中 */
    }
    th {
      background-color: #f2f2f2;
      font-weight: normal; /* 去除加粗 */
    }
    .header {
      padding-top: 30px;
      margin-bottom: 20px;
      font-size: 20px; /* 调整字体大小 */
    }
    .sub-header {
      font-size: 23px;
      font-weight: bold;
      letter-spacing: 20px; /* 设置每个字之间的间距 */
      margin-top: 30px;
    }
    p {
      margin-top: 20px;
      font-size: 16px;
    }
  </style>
</head>
<body>
<div class="container">
  <div class="header">文件名</div>
  <div class="sub-header">准    考    证</div>
  <p>此证必须与有效的身份证原件同时使用,缺一不得进入考场</p>

  <table>
    <tr>
      <th >姓名:</th>
      <td th:text="${examData.name}"></td>
      <th>性别:</th>
      <td th:text="${examData.gender}"></td>
      <th>身份证号:</th>
      <td th:text="${examData.identity}"></td>
    </tr>
    <tr>
      <th>准考证号:</th>
      <td th:text="${examData.examId}"></td>
      <th>试场号:</th>
      <td th:text="${examData.roomId}"></td>
      <th>座位号:</th>
      <td th:text="${examData.seatsId}"></td>
    </tr>
    <tr>
      <th>报考单位:</th>
      <td th:text="${examData.organization}"></td>
      <th>职位:</th>
      <td colspan="3" th:text="${examData.occupation}"></td>
    </tr>
    <tr>
      <th>考点地址:</th>
      <td colspan="5" th:text="${examData.address}"></td>
    </tr>
      <tr>
        <th>考试科目</th>
        <th>考试日期</th>
        <th>考试时间</th>
        <th colspan="4">监考人员收卷签名</th>
      </tr>
      <!-- 数据行,对应<th>下的<td> -->
      <tr>
        <td th:text="${examData.subject1}"></td>
        <td th:text="${examData.subject1Date}"></td>
        <td th:text="${examData.subject1Starttime} + ' - ' + ${examData.subject1Endtime}"></td>
        <!-- 这里使用rowspan合并 -->
        <td rowspan="2" colspan="4"></td>
      </tr>
      <tr>
        <td th:text="${examData.subject2}"></td>
        <td th:text="${examData.subject2Date}"></td>
        <td th:text="${examData.subject2Starttime} + ' - ' + ${examData.subject2Endtime}"></td>
      </tr>
    <tr>
      <td colspan="6" style="text-align: center;">交卷后,此证须经监考人员收签名,否则,答卷缺少责任由考生自负。</td>
    </tr>
  </table>
</div>
</body>
</html>

实现效果

总结

通过以上步骤,我们成功实现了一个PDF生成的功能。我们利用Spring Boot的特性,结合iText库,能够灵活地生成和下载PDF文档。同时,良好的错误处理机制确保了用户在操作过程中能够获得及时的反馈。希望本文对你理解PDF生成有所帮助!

Thymeleaf核心原理与Spring Boot集成实战:从Web渲染到PDF生成 模板引擎是现代Web开发中分离视图与业务逻辑的核心组件,它通过预定义的语法将动态数据与静态模板结合,生成最终的HTML输出。其工作原理通常包括模板解析、数据绑定和渲染输出三个阶段。在Java生态中,Thymeleaf凭借其‘自然模板’设计哲学脱颖而出,它允许模板文件本身就是合法的HTML,可直接在浏览器预览,极大地优化了前后端协作流程。这一特性不仅提升了Web页面开发效率,更使其技术价值延伸至动态内容生成的广阔领域,例如合同、报表等格式化文档的自动化生产。结合Spring Boot的自动配置能力,Thyme 阅读详情

相关推荐

Thymeleaf模板引擎:从核心语法到Spring Boot集成PDF生成实战

模板引擎是现代Web开发中分离视图与业务逻辑的关键技术,它通过特定的语法规则将动态数据嵌入静态模板,实现页面的动态渲染。其核心原理在于解析模板中的占位符或指令,并用服务器端的数据进行替换,最终生成可响应的HTML。这项技术的价值在于提升开发效率、保证代码可维护性,并促进前后端协作。在Java生态中,模板引擎广泛应用于MVC架构的视图层,特别是在Spring Boot构建的Web应用中。本文聚焦Thymeleaf这一“自然模板”引擎,它允许模板文件作为合法的HTML被浏览器直接预览,同时通过丰富的表达式语法(

weixin_33694620的博客 366

thymeleaf框架通过java渲染html生成pdf

java工程中将word格式模板类型在浏览器中以pdf格式下载或预览,使用thymeleaf前端框架,maven工程的demo。

Spring Boot 实现 PDF 导出】

选择iText如果你需要生成复杂的PDF文档,尤其是涉及到安全性和高级功能的企业级应用。iText提供了最全面的功能和最佳的性能,但需要注意其商业许可要求。选择ApachePDFBox如果你希望保持完全开源,并且只需要生成简单的PDF文档PDFBox轻量级且易于上手,适合小型项目或对性能要求不高的场景。选择JasperReports如果你需要生成复杂的报表,特别是涉及到分组、图表、子报表等功能。JasperReports是一个功能强大且成熟的工具,适合企业级应用。

neeef_se的博客 966

thymeleaf_3.0.5_中文手册.pdf

Thymeleaf是一个Java库。它是一个XML / XHTML / HTML5模板引擎,能够应用于转换模板文件,以显示您的应用程序产生的数据和文本。 它尤其适合于基于XHTML / HTML5的web服务应用程序,同时它可以处理任何XML文件,作为web或独立的应用程序。 Thymeleaf的主要目的是提供一个优雅和格式良好的方式创建模板。为了实现这一目标,它把预定义的逻辑放在XML的标记和属性上,而不是显式放在XML标记的内容上。 依靠智能缓存去解析文件,致使其执行期间的I / O操作达到了最少数量,因此其处理的模板的能力实非常快速的。

spring boot使用thymeleaf模板引擎实现html文件转pdf的实现过程

html与thymeleaf的集合实现内容的渲染最后由后端生成目标文件 html内容汉字的样式渲染,以及相关坑的说明 模板页眉和页脚可使用html标签实现自定义样式功能 实现文字水印和图片水印的方法 传给前端可以是文件流也可以是上传到文件管理后的文件地址

weixin_42562259的博客 6743

Spring Boot——Thymeleaf生成PDF实战教程

Spring Boot——Thymeleaf生成PDF实战教程

小甘说码的博客 9013

Spring Boot + Flying Saucer + Thymeleaf PDF 完整指南

本方案基于三个核心技术组件协同实现 PDF 生成,各组件职责清晰、分工明确,共同完成从数据到 PDF 文档的转换流程:组件作用核心优势将 HTML/CSS 渲染为 PDF支持 CSS 2.1 标准,所见即所得,轻量高效OpenPDFFlying Saucer 底层 PDF 实现开源免费,支持中文、PDF加密、书签等高级功能Thymeleaf动态 HTML 模板渲染与 Spring Boot 无缝集成,支持数据绑定、条件渲染。

qq_49474843的博客 1140

PDF生成导出:Spring Boot文档生成终极指南

在现代化的企业应用开发中,PDF文档生成和导出功能已经成为不可或缺的核心需求。无论是生成财务报表、业务单据,还是导出数据报表,Spring Boot都提供了多种高效的解决方案。本文将为您详细介绍Spring Boot项目中PDF生成和导出的完整实现方案,帮助您快速集成文档生成功能。 ## 🚀 Spring Boot PDF生成核心方案 ### 1. 集成UReport2报表引擎 URepo

gitblog_00917的博客 1111

OpenHTMLtoPDFSpring Boot集成:构建现代化PDF服务

OpenHTMLtoPDF是一款基于JVM的HTML转PDF库,它构建在Flying Saucer和Apache PDFBox 2之上,支持SVG图像和无障碍PDF(WCAG、Section 508、PDF/UA)。本文将详细介绍如何将OpenHTMLtoPDFSpring Boot框架无缝集成,快速搭建功能强大的PDF生成服务。 ## 📋 准备工作:环境与依赖配置 ### 1. 项目克隆

gitblog_00935的博客 971

Thymeleaf模板引擎实战:从基础语法到PDF生成Spring Boot集成

模板引擎是Web开发中实现动态内容渲染的核心技术,其原理是将静态模板与动态数据结合,生成最终的HTML输出。在Java生态中,Thymeleaf凭借其“自然模板”特性脱颖而出,模板文件本身就是有效的HTML,可直接在浏览器预览,极大提升了前后端协作效率。其技术价值在于无缝集成Spring生态,简化服务端渲染流程,尤其适合快速开发内部管理系统、生成邮件模板和PDF报告等场景。例如,结合Flying Saucer库,开发者能高效实现带页码的PDF导出功能。本文聚焦Thymeleaf的核心语法、布局管理及与Spr

weixin_32050773的博客 328

Spring Boot 引入 Thymeleaf 及入门使用

Spring Boot学习笔记(十四):Spring Boot 推荐我们使用模板引擎 Thymeleaf开发页面,因为它语法简单,功能强大。作为模板引擎,Thymeleaf 和市面上主流其他的 Java 模板引擎:JSP、Velocity、Freemarker,原理都是类似的。 模板引擎的作用:将模板(我们开发的页面)和 数据进行整合,然后输出内...

扛麻袋的少年的博客 6927
上一篇: jieba(结巴)分词整和Elasticsearch
Java30jin
博客等级 码龄4年 18粉丝 2原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值