当前位置: 首页 > news >正文

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

在 Spring Boot 项目中,生成 PDF 报表或发票是常见需求。本文将介绍如何使用 Spring Boot 集成 Thymeleaf 模板引擎和 Flying Saucer 实现 PDF 导出,并提供详细的代码实现和常见问题解决方案。


目录

      • 一、项目依赖
      • 二、创建 Thymeleaf 模板
      • 三、创建 PDF 生成工具类
      • 四、在 Spring Boot 中使用 PDF 生成功能
      • 五、常见错误及解决方案
        • 1. 中文字符乱码
        • 2. 图片加载失败
        • 3. 样式不生效
        • 4. 模板路径识别错误
        • 5. 依赖冲突
        • 6. 内存不足
      • 总结

一、项目依赖

要实现 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 渲染 HTMLContext 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 转换为 PDFtry (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 导出是生成发票、报告等文档的高效方式。通过以上实现步骤和常见问题解决方案,希望可以帮助您顺利在项目中集成此功能。

相关文章:

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

在 Spring Boot 项目中&#xff0c;生成 PDF 报表或发票是常见需求。本文将介绍如何使用 Spring Boot 集成 Thymeleaf 模板引擎和 Flying Saucer 实现 PDF 导出&#xff0c;并提供详细的代码实现和常见问题解决方案。 目录 一、项目依赖二、创建 Thymeleaf 模板三、创建 PDF 生…...

web——upload1——攻防世界

第一次做木马题目&#xff0c;有点懵逼&#xff0c;浮现一下做题思路 可以上传一个文件&#xff0c;通过学习学习到了一句话木马 一句话木马&#xff1a; 利用文件上传漏洞&#xff0c;往目标网站中上传一句话木马&#xff0c;然后你就可以在本地通过中国菜刀chopper.exe即可…...

nginx 搭建网站

1.查看防火墙状态systemctl status firewalld 2.getenforce 3.安装nginx yum install nginx -y 4.网站信息 echo "welcome to yinchuankejixuanyuan" > /usr/share/nginx/html/index.html 5.查看命令状态 nginx -t 6.重启 systemctl restart nginx...

Java基础-Java中的常用类(上)

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 String类 创建字符串 字符串长度 连接字符串 创建格式化字符串 String 方法 System类 常用方法 方…...

气压仪器智能打气泵方案芯片SIC8833

智能打气泵方案最开始是机械式的开发&#xff0c;后来慢慢地演变成由一个气缸、压力传感器和主控芯片的开发的PCBA方案&#xff0c;它具备小体积、智能数显、预设胎压、动态测量、精准压力检测以及过充过放等功能。 其方案设计原理是利用主控芯片和压力传感器的组合设计&#x…...

软件测试(系统测试)的定位和专业:完善产品;专业;非助手;自动化

软件测试&#xff08;系统测试&#xff09;的定位 在研发流程的后端&#xff0c;测试并非无中生有的创举&#xff0c;而是从既有基础&#xff08;即“1”&#xff09;出发&#xff0c;致力于推动产品向更高层次&#xff08;即从“1”到“100”&#xff09;的跃升与完善。在这一…...

2024 CSS保姆级教程四

CSS中的动画 CSS动画&#xff08;CSS Animations&#xff09;是为层叠样式表建议的允许可扩展标记语言&#xff08;XML&#xff09;元素使用CSS的动画的模块​ 即指元素从一种样式逐渐过渡为另一种样式的过程​ 常见的动画效果有很多&#xff0c;如平移、旋转、缩放等等&#…...

PostgreSQL技术内幕17:PG分区表

文章目录 0.简介1.概念介绍2.分区表技术产生的背景3.分区类型及使用方式4.实现原理4.1 分区表创建4.2 分区表查询4.3 分区表写入4.4 分区表删除 0.简介 本文主要介绍PG中分区表的概念&#xff0c;产生分区表技术的原因&#xff0c;使用方式和其内部实现原理&#xff0c;旨在能…...

群控系统服务端开发模式-应用开发-上传工厂开发

现在的文件、图片等上传基本都在使用oss存储。而现在常用的oss存储有阿里云、腾讯云、七牛云、华为云等&#xff0c;但是用的最多的还是前三种。而我主要封装的是本地存储、阿里云存储、腾讯云存储、七牛云存储。废话不多说&#xff0c;直接上传设计图及说明&#xff0c;就一目…...

【Docker系列】指定系统平台拉取 openjdk:8 镜像

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

语音识别:docker部署FunASR以及springboot集成funasr

内容摘选自: https://github.com/modelscope/FunASR/blob/main/runtime/docs/SDK_advanced_guide_offline_zh.md FunASR FunASR是一个基础语音识别工具包&#xff0c;提供多种功能&#xff0c;包括语音识别&#xff08;ASR&#xff09;、语音端点检测&#xff08;VAD&#xf…...

Rust项目结构

文章目录 一、module模块1.文件内的module 二、模块化项目结构1.关于module2.各个模块之间互相引用 三、推荐项目结构1.实例 参考 一、module模块 1.文件内的module 关键字&#xff1a;mod 引入模块中的方法 usemod名字&#xff1a;方法名usemod名字.*写全路径 二、模块化项…...

计算并联电阻的阻值

计算并联电阻的阻值 C语言代码C代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 对于阻值为r1和r2的电阻&#xff0c;其并联电阻阻值公式计算如下&#xff1a; R1/(1/r11/r2) 输入 两个电阻阻抗大小&#xff0c;浮…...

MySQL符号类型(详细)

在 MySQL 中&#xff0c;符号可以分为几种主要类型&#xff0c;以下是所有符号类型的小写分类&#xff1a; 1. 占位符 ?&#xff1a;用于准备语句中的占位符&#xff0c;表示将来要替换的值。 2. 分隔符 ;&#xff1a;表示 sql 语句的结束。 ,&#xff1a;用于分隔列、值或…...

Angular引用控件类

说明&#xff1a; angular 在一个控件类里面&#xff0c;引入另外一个控件类&#xff0c;这样做的好处&#xff0c;就是代码分离&#xff0c;当你一个页面存在多少类似于独立的界面时&#xff0c;可以使用这种方式&#xff0c;分离代码 更好维护程序 效果图&#xff1a; step…...

stm32 踩坑笔记

串口问题&#xff1a; 问题&#xff1a;会改变接收缓冲的下一个字节 串口的初始化如下&#xff0c;位长度选择了9位。因为要奇偶校验&#xff0c;要选择9位。但是接收有用数据只用到1个字节。 问题原因&#xff1a; 所以串口接收时会把下一个数据更改...

文件上传和文件包含

声明: 本文章只是适用于网络安全教学,请自觉遵守网络安全法,严禁用于非法途径,若读者做出来任何危害网络安全的行为,后果自负,均与本人无关. 文件上传&#xff1a; 大部分的网站和应用系统都有上传的功能&#xff0c;如用户头像上传&#xff0c;图片上传&#xff0c;文档上传…...

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十八集补充:制作空洞骑士独有的EventSystem和InputModule

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作空洞骑士独有的EventSystem和InputModule总结 前言 hello大家好久没见&#xff0c;之所以隔了这么久才更新并不是因为我又放弃了这个项目&#xff0c;而…...

yelp数据集上试验SVD,SVDPP,PMF,NMF 推荐算法

SVD、SVD、PMF 和 NMF 是几种常见的推荐算法&#xff0c;它们主要用于协同过滤和矩阵分解方法来生成个性化推荐。下面是对每种算法的简要介绍&#xff1a; 1. SVD&#xff08;Singular Value Decomposition&#xff09; 用途&#xff1a;SVD 是一种矩阵分解技术&#xff0c;通…...

计算机视觉常用数据集Cityscapes的介绍、下载、转为YOLO格式进行训练

我在寻找Cityscapes数据集的时候花了一番功夫&#xff0c;因为官网下载需要用公司或学校邮箱邮箱注册账号&#xff0c;等待审核通过后才能进行下载数据集。并且一开始我也并不了解Cityscapes的格式和内容是什么样的&#xff0c;现在我弄明白后写下这篇文章&#xff0c;用于记录…...

Debian服务器网络配置二选一:告别network与NetworkManager冲突,保姆级教程教你选对工具

Debian服务器网络配置终极指南&#xff1a;network与NetworkManager深度解析与实战选择 在Linux系统中&#xff0c;网络配置是系统管理员和开发者必须掌握的核心技能之一。Debian作为最流行的Linux发行版之一&#xff0c;提供了两种主要的网络管理工具&#xff1a;传统的ifupdo…...

别再只盯着P0XXX了!一文搞懂UDS诊断中DTC的三个字节到底在说什么(附实战解析)

解码UDS诊断中的DTC三字节&#xff1a;从十六进制到故障真相 当诊断仪屏幕上跳出"0x43E711"这样的神秘代码时&#xff0c;多数工程师的第一反应是翻查故障码手册。但真正的高手会像破译密码一样&#xff0c;直接拆解这三个字节背后的工程语言。本文将带您深入DTC的二…...

[模型解析] GPT: 模型演进分析从GPT-3到GPT-5.5

GPT 模型演进分析&#xff1a;从 GPT-3 到 GPT-5.5 OpenAI 的 GPT 系列模型在过去几年经历了快速演进&#xff0c;从 2020 年的 GPT-3 到 2026 年的 GPT-5.5&#xff0c;每一次迭代都带来了显著的能力提升和架构创新。本文将系统分析 GPT 模型的演进路径与技术特点。 一、GPT 模…...

Unity 2020.3.x下HybridCLR热更新落地实战指南

1. 这不是“加个插件就能热更”的童话&#xff0c;而是Unity 2020.3.x下HybridCLR落地的真实切片很多人第一次听说HybridCLR&#xff0c;是在某篇标题写着“Unity热更新终极方案”的公众号推文里。点进去&#xff0c;看到几行代码、一个Build按钮、一段“热更成功”的日志截图&…...

金仓数据库KingbaseES自动创建表空间目录:简化运维,适配国产生态

目录 一、前言&#xff1a;传统表空间创建的运维痛点 二、自动创建表空间目录核心方案 2.1 核心控制参数 2.2 功能强制约束条件 2.3 多场景实操测试&#xff08;含大小写混合路径&#xff09; 场景1&#xff1a;目标目录已存在 场景2&#xff1a;目标目录部分存在 场景…...

AI-native开发:从工具使用者到智能体编排工程师的范式跃迁

1. 这不是“学AI工具”&#xff0c;而是重构整个开发认知体系“AI-native软件开发者”这个说法最近在技术社区刷屏&#xff0c;但很多人一上来就去狂刷Copilot快捷键、背Prompt模板、堆砌LLM API调用——这就像当年刚有IDE时&#xff0c;有人花三个月专门练CtrlShiftF的肌肉记忆…...

C++ Kafka实战:用librdkafka手写一个带自定义分区和事件回调的生产者

C Kafka实战&#xff1a;构建高性能生产者客户端的深度实践 在分布式系统架构中&#xff0c;消息队列作为解耦生产者和消费者的关键组件&#xff0c;其重要性不言而喻。而Apache Kafka凭借其高吞吐、低延迟和水平扩展能力&#xff0c;已成为现代实时数据管道和流处理应用的首选…...

Gemini3.1Pro构建神经符号系统实战

用 Gemini 3.1 Pro 构建神经符号系统的可行性探讨&#xff1a;从“会推理”到“能落地执行”在大模型时代&#xff0c;大家越来越关心的不只是“模型会不会回答”&#xff0c;而是能不能把推理可靠地用到复杂任务里&#xff1a;比如自动化规划、合规决策、工具调用、甚至半自动…...

3步搞定M3U8视频下载:N_m3u8DL-CLI-SimpleG图形界面终极指南

3步搞定M3U8视频下载&#xff1a;N_m3u8DL-CLI-SimpleG图形界面终极指南 【免费下载链接】N_m3u8DL-CLI-SimpleG N_m3u8DL-CLIs simple GUI 项目地址: https://gitcode.com/gh_mirrors/nm3/N_m3u8DL-CLI-SimpleG 你是否曾经遇到过在线视频无法保存的烦恼&#xff1f;特别…...

AI导演系统:编排角色扮演,让多智能体协作效率飙升10倍

&#x1f9d1;‍&#x1f4bb; 博主介绍 & 诚邀关注 作者&#xff1a;专注于 Java、Python、前端开发的技术博主 | 全网粉丝 30 万 在校期间协助导师完成毕业设计课题分类、论文格式初审及代码整理工作&#xff1b;工作后持续分享毕设思路&#xff0c;助力毕业生顺利完成…...