使用SpringBoot集成Thymeleaf和Flying?Saucer實現(xiàn)PDF導(dǎo)出
一、項目依賴
要實現(xiàn) PDF 導(dǎo)出功能,首先需要在項目中添加以下依賴:
<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,確保使用正確版本以避免依賴沖突。
二、創(chuàng)建 Thymeleaf 模板
新建一個 HTML 模板用于生成發(fā)票內(nèi)容,例如在 resources/templates/pdf/invoice.html 文件中編寫如下 HTML:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>發(fā)票</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>發(fā)票</h1>
<p>發(fā)票編號:<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>數(shù)量</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>
三、創(chuàng)建 PDF 生成工具類
接下來,創(chuàng)建 PdfUtil 工具類,通過 Thymeleaf 渲染 HTML 并使用 Flying Saucer 將 HTML 轉(zhuǎn)為 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 轉(zhuǎn)換為 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("發(fā)票PDF 生成失敗");
}
}
}
四、在 Spring Boot 中使用 PDF 生成功能
在 Spring Boot 控制器中調(diào)用 PdfUtil.generateInvoicePdf,將生成的 PDF 返回給用戶或作為附件發(fā)送郵件:
@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 中,中文字符可能出現(xiàn)亂碼。
- 解決方案:確保
addFont引用支持中文的字體文件(如simhei.ttf)。
2. 圖片加載失敗
問題:HTML 中的圖片在 PDF 中無法正常顯示。
解決方案:將圖片路徑設(shè)置為絕對路徑或通過
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,與其他依賴產(chǎn)生沖突。
- 解決方案:獨立模塊管理依賴,使用
maven-shade-plugin處理沖突類。
6. 內(nèi)存不足
- 問題:生成大型 PDF 時出現(xiàn)內(nèi)存溢出。
- 解決方案:增加 JVM 內(nèi)存配置,或簡化 HTML 結(jié)構(gòu)降低內(nèi)存占用。
總結(jié)
使用 Spring Boot 集成 Thymeleaf 和 Flying Saucer 實現(xiàn) PDF 導(dǎo)出是生成發(fā)票、報告等文檔的高效方式。通過以上實現(xiàn)步驟和常見問題解決方案,希望可以幫助您順利在項目中集成此功能。
以上就是使用SpringBoot集成Thymeleaf和Flying Saucer實現(xiàn)PDF導(dǎo)出的詳細內(nèi)容,更多關(guān)于SpringBoot實現(xiàn)PDF導(dǎo)出的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)與算法之插入排序詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之插入排序,結(jié)合實例形式分析了java插入排序的概念、分類、原理、實現(xiàn)方法與相關(guān)注意事項,需要的朋友可以參考下2017-05-05
Java中FilterInputStream和FilterOutputStream的用法詳解
這篇文章主要介紹了Java中FilterInputStream和FilterOutputStream的用法詳解,這兩個類分別用于封裝輸入和輸出流,需要的朋友可以參考下2016-06-06
Spring Boot 3 中 WebFilter 的執(zhí)行順序流程分析
Spring Boot中管理WebFilter順序,默認為Integer.MAX_VALUE,需顯式使用@Order或Ordered接口定義優(yōu)先級,請求階段按順序值從小到大執(zhí)行,響應(yīng)階段按從大到小,相同順序值依賴Bean注冊順序,本文詳細說明在Spring Boot 3中如何管理這些過濾器的執(zhí)行流程,需要的朋友一起看看吧2025-08-08
jackson在springboot中的使用方式-自定義參數(shù)轉(zhuǎn)換器
這篇文章主要介紹了jackson在springboot中的使用方式-自定義參數(shù)轉(zhuǎn)換器,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
SSH框架網(wǎng)上商城項目第28戰(zhàn)之使用Ajax技術(shù)局部更新商品數(shù)量和總價
這篇文章主要為大家詳細介紹了SSH框架網(wǎng)上商城項目第28戰(zhàn)之使用Ajax技術(shù)局部更新商品數(shù)量和總價,感興趣的小伙伴們可以參考一下2016-06-06
SpringBoot中使用@Async實現(xiàn)異步任務(wù)調(diào)用詳解
這篇文章主要介紹了SpringBoot中使用@Async實現(xiàn)異步任務(wù)調(diào)用詳解,一個可以無需等待被調(diào)用函數(shù)的返回值就讓操作繼續(xù)進行的方法(來自百度百科),即程序在順序執(zhí)行時,不等待異步調(diào)用的語句返回結(jié)果就執(zhí)行后面的程序,需要的朋友可以參考下2023-12-12
SpringBoot項目優(yōu)雅的全局異常處理方式(全網(wǎng)最新)
這篇文章主要介紹了SpringBoot項目優(yōu)雅的全局異常處理方式(全網(wǎng)最新),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

