使用SpringBoot集成Thymeleaf和Flying Saucer实现PDF导出

 更新时间:2024年11月07日 08:36:58   作者:( •̀∀•́ )920  
在 Spring Boot 项目中,生成 PDF 报表或发票是常见需求,本文将介绍如何使用 Spring Boot 集成 Thymeleaf 模板引擎和 Flying Saucer 实现 PDF 导出,并提供详细的代码实现和常见问题解决方案,需要的朋友可以参考下

一、项目依赖

要实现 PDF 导出功能,首先需要在项目中添加以下依赖:

<dependencies>
    <!-- Thymeleaf模板引擎 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- Flying Saucer for PDF generation -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf</artifactId>
        <version>9.1.22</version>
    </dependency>

    <!-- iTextPDF (com.lowagie 版本,用于兼容 Flying Saucer) -->
    <dependency>
        <groupId>com.lowagie</groupId>
        <artifactId>itext</artifactId>
        <version>2.1.7</version>
    </dependency>
</dependencies>

注意:Flying Saucer 使用的是旧版 iText 库 com.lowagie,而不是新版 com.itextpdf,确保使用正确版本以避免依赖冲突。

二、创建 Thymeleaf 模板

新建一个 HTML 模板用于生成发票内容,例如在 resources/templates/pdf/invoice.html 文件中编写如下 HTML:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>发票</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        h1 { text-align: center; }
        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .total { font-weight: bold; }
        .footer { margin-top: 30px; text-align: center; font-size: 12px; color: #888; }
    </style>
</head>
<body>
<h1>发票</h1>
<p>发票编号:<span th:text="${invoiceNumber}"></span></p>
<p>开具日期:<span th:text="${invoiceDate}"></span></p>
<p>买家姓名:<span th:text="${buyerName}"></span></p>

<h2>商品详情</h2>
<table>
    <thead>
    <tr>
        <th>商品名称</th>
        <th>描述</th>
        <th>数量</th>
        <th>单价</th>
        <th>小计</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="item : ${goodsItems}">
        <td th:text="${item.goodsName}"></td>
        <td th:text="${item.goodsDesc}"></td>
        <td th:text="${item.quantity}"></td>
        <td th:text="${item.unitPrice}"></td>
        <td th:text="${item.totalPrice}"></td>
    </tr>
    </tbody>
</table>

<p class="total">总金额:<span th:text="${finalAmount}"></span></p>
<div class="footer">感谢您的购买!</div>
</body>
</html>

三、创建 PDF 生成工具类

接下来,创建 PdfUtil 工具类,通过 Thymeleaf 渲染 HTML 并使用 Flying Saucer 将 HTML 转为 PDF:

package com.xyh.transaction.utils;

import com.xyh.transaction.entity.dto.goods.GoodsInvoice;
import com.xyh.transaction.exception.BusinessException;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.ByteArrayOutputStream;
import java.util.List;

public class PdfUtil {

    public static byte[] generateInvoicePdf(String buyerName, String invoiceNumber,
                                            List<GoodsInvoice> goodsItems, String finalAmount) {
        TemplateEngine templateEngine = new TemplateEngine();

        // 使用 Thymeleaf 渲染 HTML
        Context context = new Context();
        context.setVariable("buyerName", buyerName);
        context.setVariable("invoiceNumber", invoiceNumber);
        context.setVariable("goodsItems", goodsItems);
        context.setVariable("finalAmount", finalAmount);
        String htmlContent = templateEngine.process("pdf/invoice.html", context);

        // 将 HTML 转换为 PDF
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            ITextRenderer renderer = new ITextRenderer();
            renderer.getFontResolver().addFont("/path/to/your/font/simhei.ttf", true); // 防止中文乱码
            renderer.setDocumentFromString(htmlContent);
            renderer.layout();
            renderer.createPDF(outputStream);
            return outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("发票PDF 生成失败");
        }
    }
}

四、在 Spring Boot 中使用 PDF 生成功能

在 Spring Boot 控制器中调用 PdfUtil.generateInvoicePdf,将生成的 PDF 返回给用户或作为附件发送邮件:

@RestController
@RequestMapping("/invoice")
public class InvoiceController {

    @GetMapping("/generate")
    public ResponseEntity<byte[]> generateInvoice() {
        byte[] pdfBytes = PdfUtil.generateInvoicePdf("张三", "INV-12345",
                goodsItems, "1000.00");
        
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_PDF);
        headers.setContentDispositionFormData("attachment", "invoice.pdf");
        
        return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK);
    }
}

五、常见错误及解决方案

1. 中文字符乱码

  • 问题:生成的 PDF 中,中文字符可能出现乱码。
  • 解决方案:确保 addFont 引用支持中文的字体文件(如 simhei.ttf)。

2. 图片加载失败

  • 问题:HTML 中的图片在 PDF 中无法正常显示。

  • 解决方案:将图片路径设置为绝对路径或通过 setBaseURL 指定资源根路径:

renderer.getSharedContext().setBaseURL("file:/path/to/resources/");

3. 样式不生效

  • 问题:Flying Saucer 不支持高级 CSS。
  • 解决方案:使用基本的 table 布局和简单 CSS,不依赖 flex、CSS 变量等。

4. 模板路径识别错误

  • 问题:模板引擎找不到指定 HTML 文件。
  • 解决方案:检查文件路径和模板配置,确保模板放置在 resources/templates/pdf 目录下。

5. 依赖冲突

  • 问题:Flying Saucer 使用旧版 iText,与其他依赖产生冲突。
  • 解决方案:独立模块管理依赖,使用 maven-shade-plugin 处理冲突类。

6. 内存不足

  • 问题:生成大型 PDF 时出现内存溢出。
  • 解决方案:增加 JVM 内存配置,或简化 HTML 结构降低内存占用。

总结

使用 Spring Boot 集成 Thymeleaf 和 Flying Saucer 实现 PDF 导出是生成发票、报告等文档的高效方式。通过以上实现步骤和常见问题解决方案,希望可以帮助您顺利在项目中集成此功能。

以上就是使用SpringBoot集成Thymeleaf和Flying Saucer实现PDF导出的详细内容,更多关于SpringBoot实现PDF导出的资料请关注脚本之家其它相关文章!

相关文章

  • Java多线程优化方法及使用方式

    Java多线程优化方法及使用方式

    这篇文章主要介绍了Java多线程优化方法及使用方式,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • 关于Java中使用jdbc连接数据库中文出现乱码的问题

    关于Java中使用jdbc连接数据库中文出现乱码的问题

    这篇文章主要介绍了关于Java中使用jdbc连接数据库中文出现乱码的问题,默认的编码和数据库表中的数据使用的编码是不一致的,如果是中文,那么在数据库中执行时已经是乱码了,需要的朋友可以参考下
    2023-04-04
  • 详解Java对象的内存布局

    详解Java对象的内存布局

    这篇文章主要介绍了Java对象的内存布局,对对象内存感兴趣的同学,一定要仔细研究下
    2021-04-04
  • JSP页面pageEncoding和contentType属性

    JSP页面pageEncoding和contentType属性

    有关于JSP页面中pageEncoding和contentType属性。
    2013-04-04
  • idea导入module全流程

    idea导入module全流程

    这篇文章主要介绍了idea导入module全流程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • MybatisPlus关联查询的完美实现方案

    MybatisPlus关联查询的完美实现方案

    我们在项目开发的时候,难免会遇到连表查询的操作,所以下面这篇文章主要给大家介绍了关于MybatisPlus关联查询的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2021-12-12
  • Java中与数字相关的常用类的用法详解

    Java中与数字相关的常用类的用法详解

    在我们的代码中,经常会遇到一些数字&数学问题、随机数问题、日期问题和系统设置问题等,为了解决这些问题,Java给我们提供了多个处理相关问题的类,比如Number类、Math类、Random类等等,本篇文章我们先从Number数字类和Math数学类学起
    2023-05-05
  • SpringBoot使用JavaMailSender实现发送邮件

    SpringBoot使用JavaMailSender实现发送邮件

    JavaMailSender是Spring Framework中的一个接口,用于发送电子邮件,本文主要为大家详细介绍了SpringBoot如何使用JavaMailSender实现发送邮件,需要的可以参考下
    2023-12-12
  • 一篇文章带你了解Java基础-接口

    一篇文章带你了解Java基础-接口

    这篇文章主要介绍了java接口基础知识,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-08-08
  • Java Spring boot 配置JDK和MAVEN开发环境的过程

    Java Spring boot 配置JDK和MAVEN开发环境的过程

    本文详细介绍了如何配置JDK和Maven环境,包括JDK的安装与环境变量设置,Maven的下载、配置环境变量和设置阿里云仓库,最后简述了在IntelliJ IDEA中配置JDK和Maven的步骤,本教程适合Java开发新手进行开发环境的搭建,确保顺利进行Java项目的开发
    2024-11-11

最新评论