SpringBoot導(dǎo)出PDF的四種實(shí)現(xiàn)方法詳解
在Spring Boot應(yīng)用程序中實(shí)現(xiàn)PDF導(dǎo)出功能,可以選擇多種庫和技術(shù)棧。每種方法都有其優(yōu)缺點(diǎn),適用于不同的場景。以下是四種常見的方式:iText、Apache PDFBox、JasperReports 和 Thymeleaf + Flying Saucer。我將詳細(xì)對(duì)比這些方法,并提供相應(yīng)的代碼示例。
1. iText
優(yōu)點(diǎn):
- 豐富的API: 支持復(fù)雜的PDF操作,如加密、數(shù)字簽名、表單處理等。
- 企業(yè)級(jí)支持: 提供廣泛的文檔和支持社區(qū)。
- 多格式輸出: 除了PDF,還支持其他格式(如HTML、XML)的轉(zhuǎn)換。
缺點(diǎn):
- 商業(yè)許可: iText 7 是商業(yè)軟件,某些高級(jí)功能需要購買許可證。
- 學(xué)習(xí)曲線: API較為復(fù)雜,可能需要一定的學(xué)習(xí)成本。
性能:
對(duì)于大多數(shù)應(yīng)用場景來說,iText 的性能是足夠的。它在內(nèi)存管理和文件處理速度方面表現(xiàn)優(yōu)秀,尤其適合處理復(fù)雜的PDF文檔。
適用場景:
適合需要生成復(fù)雜PDF文檔的應(yīng)用,尤其是那些涉及安全性和高級(jí)功能的企業(yè)級(jí)應(yīng)用。
示例代碼:
<!-- 添加依賴 --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.1.15</version> <!-- 請(qǐng)檢查并使用最新版本 --> </dependency>
import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfWriter; import com.itextpdf.layout.Document; import com.itextpdf.layout.element.Paragraph; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ITextPdfService { public void export(HttpServletResponse response) throws IOException { // 設(shè)置響應(yīng)頭 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=users.pdf"); try (PdfWriter writer = new PdfWriter(response.getOutputStream()); PdfDocument pdf = new PdfDocument(writer); Document document = new Document(pdf)) { // 添加內(nèi)容到PDF document.add(new Paragraph("Hello, this is a PDF document created with iText in Spring Boot!")); // 關(guān)閉文檔 document.close(); } } }
2. Apache PDFBox
優(yōu)點(diǎn):
- 完全開源: 沒有商業(yè)限制,適合所有類型的項(xiàng)目。
- 輕量級(jí): 依賴項(xiàng)較少,項(xiàng)目結(jié)構(gòu)簡潔。
- 易于上手: API相對(duì)簡單,適合快速開發(fā)和學(xué)習(xí)。
缺點(diǎn):
- 功能有限: 在一些復(fù)雜的功能上,如處理大型PDF或執(zhí)行高級(jí)操作,可能不如iText強(qiáng)大。
- 性能問題: 在處理非常大的文件或高并發(fā)場景下,性能可能會(huì)略遜于iText。
性能:
PDFBox 在處理較小的PDF文件時(shí)表現(xiàn)良好,但在處理大文件或者高并發(fā)場景下,其性能可能會(huì)略遜于iText。
適用場景:
適合需要生成簡單PDF文檔的應(yīng)用,尤其是那些希望保持完全開源的項(xiàng)目。
示例代碼:
<!-- 添加依賴 --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.27</version> <!-- 請(qǐng)檢查并使用最新版本 --> </dependency>
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.font.PDType1Font; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class PdfBoxPdfService { public void export(HttpServletResponse response) throws IOException { // 設(shè)置響應(yīng)頭 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=users.pdf"); try (PDDocument document = new PDDocument()) { PDPage page = new PDPage(); document.addPage(page); try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) { contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12); contentStream.beginText(); contentStream.newLineAtOffset(100, 700); contentStream.showText("Hello, this is a PDF document created with Apache PDFBox in Spring Boot!"); contentStream.endText(); } // 將PDF寫入響應(yīng)輸出流 document.save(response.getOutputStream()); } } }
3. JasperReports
優(yōu)點(diǎn):
- 強(qiáng)大的報(bào)表設(shè)計(jì)能力: 支持復(fù)雜的表格、圖表、分組、子報(bào)表等功能。
- 多數(shù)據(jù)源支持: 可以從數(shù)據(jù)庫、JavaBean集合、CSV、XML等多種數(shù)據(jù)源獲取數(shù)據(jù)。
- 豐富的樣式和格式化: 支持多種字體、顏色、邊框、背景等樣式設(shè)置,以及日期、數(shù)字等格式化。
- 集成度高: 與Spring Boot集成方便,可以輕松地將報(bào)表生成邏輯嵌入到應(yīng)用程序中。
- 輸出格式多樣: 除了PDF,還支持HTML、Excel、CSV等多種輸出格式。
缺點(diǎn):
- 學(xué)習(xí)曲線較陡: JRXML模板語法較為復(fù)雜,需要一定時(shí)間來掌握。
- 依賴項(xiàng)較多: 需要引入多個(gè)依賴項(xiàng),可能會(huì)增加項(xiàng)目的復(fù)雜度。
- 性能問題: 在處理非常大的數(shù)據(jù)集時(shí),可能會(huì)遇到性能瓶頸,尤其是在內(nèi)存管理和渲染速度方面。
性能:
在處理復(fù)雜報(bào)表和大數(shù)據(jù)集時(shí)表現(xiàn)較好,尤其是在需要高級(jí)功能(如分組、圖表)的情況下。
適用場景:
適合需要生成復(fù)雜報(bào)表的應(yīng)用,尤其是包含大量數(shù)據(jù)、圖表、分組等元素的場景。
適合需要支持多種輸出格式的應(yīng)用。
示例代碼:
<!-- 添加依賴 --> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>6.17.0</version> <!-- 請(qǐng)檢查并使用最新版本 --> </dependency>
import net.sf.jasperreports.engine.*; import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("/api") public class JasperReportController { @GetMapping("/export-jasper-pdf") public void export(HttpServletResponse response) throws Exception { // 設(shè)置響應(yīng)頭 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=report.pdf"); // 加載JRXML模板 InputStream reportTemplate = getClass().getResourceAsStream("/templates/report.jrxml"); JasperReport jasperReport = JasperCompileManager.compileReport(reportTemplate); // 準(zhǔn)備數(shù)據(jù) List<User> users = userService.getAllUsers(); // 假設(shè)有一個(gè)UserService類 JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(users); // 設(shè)置參數(shù) Map<String, Object> parameters = new HashMap<>(); parameters.put("title", "User Report"); // 生成PDF JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource); JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream()); } }
4. Thymeleaf + Flying Saucer
優(yōu)點(diǎn):
- HTML/CSS友好: 使用標(biāo)準(zhǔn)的HTML和CSS進(jìn)行頁面布局和樣式設(shè)置,非常適合前端開發(fā)人員。
- 易于維護(hù): HTML模板容易理解和修改,尤其適合那些已經(jīng)熟悉HTML/CSS的團(tuán)隊(duì)。
- 靈活性高: 可以輕松地將現(xiàn)有的Thymeleaf模板轉(zhuǎn)換為PDF,減少了重復(fù)工作。
- 輕量級(jí): 相對(duì)于JasperReports,F(xiàn)lying Saucer的依賴項(xiàng)較少,項(xiàng)目結(jié)構(gòu)更簡潔。
- 快速開發(fā): 對(duì)于簡單的PDF生成需求,開發(fā)速度較快,因?yàn)椴恍枰獙W(xué)習(xí)新的模板語言。
缺點(diǎn):
- 功能有限: 相比JasperReports,F(xiàn)lying Saucer的功能較為有限,特別是在處理復(fù)雜報(bào)表(如分組、圖表)時(shí)。
- 性能一般: 在處理大文件或高并發(fā)場景下,性能可能不如JasperReports。
- 樣式兼容性: 某些CSS樣式可能無法完全兼容,導(dǎo)致PDF渲染效果與預(yù)期不符。
性能:
對(duì)于簡單的PDF生成需求,性能足夠,并且開發(fā)速度快,維護(hù)成本低。
適用場景:
- 適合需要將現(xiàn)有的HTML頁面轉(zhuǎn)換為PDF的應(yīng)用,尤其是那些已經(jīng)有現(xiàn)成的HTML模板的情況。
- 適合生成簡單的文檔,如發(fā)票、合同、報(bào)告等,而不涉及復(fù)雜的報(bào)表功能。
示例代碼:
<!-- 添加依賴 --> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>3.0.12.RELEASE</version> <!-- 請(qǐng)檢查并使用最新版本 --> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf-itext5</artifactId> <version>9.1.20</version> <!-- 請(qǐng)檢查并使用最新版本 --> </dependency>
import org.springframework.core.io.ClassPathResource; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import org.xhtmlrenderer.pdf.ITextRenderer; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.nio.charset.StandardCharsets; @RestController @RequestMapping("/api") public class PdfController { private final TemplateEngine templateEngine; public PdfController(TemplateEngine templateEngine) { this.templateEngine = templateEngine; } @GetMapping("/export-thymeleaf-pdf") public void export(HttpServletResponse response) throws Exception { // 設(shè)置響應(yīng)頭 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=report.pdf"); // 加載HTML模板 InputStream templateInputStream = new ClassPathResource("templates/report.html").getInputStream(); String htmlContent = new String(templateInputStream.readAllBytes(), StandardCharsets.UTF_8); // 準(zhǔn)備上下文數(shù)據(jù) Context context = new Context(); context.setVariable("users", userService.getAllUsers()); // 假設(shè)有一個(gè)UserService類 context.setVariable("title", "User Report"); // 渲染HTML String processedHtml = templateEngine.process(htmlContent, context); // 將HTML轉(zhuǎn)換為PDF ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(processedHtml); renderer.layout(); // 輸出PDF try (OutputStream outputStream = response.getOutputStream()) { renderer.createPDF(outputStream); } } }
性能與易用性對(duì)比
iText | Apache PDFBox | JasperReports | Thymeleaf + Flying Saucer | |
性能 | 高 | 中 | 高(復(fù)雜報(bào)表) | 中(簡單文檔) |
易用性 | 復(fù)雜 | 簡單 | 復(fù)雜 | 簡單 |
功能 | 強(qiáng)大 | 有限 | 非常強(qiáng)大(報(bào)表) | 有限(HTML/CSS) |
依賴項(xiàng) | 較多(部分需商業(yè)許可) | 少 | 較多 | 少 |
適用場景 | 復(fù)雜PDF文檔 | 簡單PDF文檔 | 復(fù)雜報(bào)表 | 簡單文檔/HTML轉(zhuǎn)PDF |
學(xué)習(xí)曲線 | 陡峭 | 平緩 | 陡峭 | 平緩 |
總結(jié)
選擇 iText 如果你需要生成復(fù)雜的PDF文檔,尤其是涉及到安全性和高級(jí)功能的企業(yè)級(jí)應(yīng)用。iText 提供了最全面的功能和最佳的性能,但需要注意其商業(yè)許可要求。
選擇 Apache PDFBox 如果你希望保持完全開源,并且只需要生成簡單的PDF文檔。PDFBox 輕量級(jí)且易于上手,適合小型項(xiàng)目或?qū)π阅芤蟛桓叩膱鼍啊?/p>
選擇 JasperReports 如果你需要生成復(fù)雜的報(bào)表,特別是涉及到分組、圖表、子報(bào)表等功能。JasperReports 是一個(gè)功能強(qiáng)大且成熟的工具,適合企業(yè)級(jí)應(yīng)用。
選擇 Thymeleaf + Flying Saucer 如果你需要將現(xiàn)有的HTML頁面轉(zhuǎn)換為PDF,或者只需要生成簡單的文檔(如發(fā)票、合同等)。它易于使用,開發(fā)速度快,特別適合前端開發(fā)人員。
在實(shí)際項(xiàng)目中,建議根據(jù)具體需求和技術(shù)棧選擇合適的工具。如果你不確定哪種工具更適合,可以先嘗試一個(gè)小規(guī)模的原型項(xiàng)目,評(píng)估其性能和易用性,再做最終決定。
以上就是SpringBoot導(dǎo)出PDF的四種實(shí)現(xiàn)方法詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot導(dǎo)出PDF的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
項(xiàng)目依賴Springboot jar失敗解決方案
這篇文章主要介紹了項(xiàng)目依賴Springboot jar失敗解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08使用@RequestBody傳對(duì)象參數(shù)時(shí)碰到的坑
這篇文章主要介紹了使用@RequestBody傳對(duì)象參數(shù)時(shí)碰到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08關(guān)于Long和Integer相互轉(zhuǎn)換方式
這篇文章主要介紹了關(guān)于Long和Integer相互轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08在IDEA中安裝scala、maven、hadoop遇到的問題小結(jié)
這篇文章主要介紹了在IDEA中安裝scala、maven、hadoop遇到的問題小結(jié),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10利用hadoop查詢兩兩之間有共同好友及他倆的共同好友都是誰
一想到要實(shí)現(xiàn)求共同好友的功能,很多人都會(huì)想到redis來實(shí)現(xiàn)。但是redis存儲(chǔ)和數(shù)據(jù)和計(jì)算時(shí)需要耗費(fèi)較多的內(nèi)存資源。所以文本將介紹另一種方法,即利用Hadoop中的MapReduce來實(shí)現(xiàn),感興趣的可以了解一下2022-01-01