【Spring Boot 实现 PDF 导出】

[复制链接]
发表于 2025-10-30 06:27:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
Spring Boot 实现 PDF 导出

在Spring Boot应用步调中实现PDF导出功能,可以选择多种库和技能栈。每种方法都有其优缺点,实用于差别的场景。以下是四种常见的方式:iText、Apache PDFBox、JasperReports 和 Thymeleaf + Flying Saucer。我将具体对比这些方法,并提供相应的代码示例。

1. iText

长处:


  • 丰富的API: 支持复杂的PDF操纵,如加密、数字署名、表单处理惩罚等。
  • 企业级支持: 提供广泛的文档和支持社区。
  • 多格式输出: 除了PDF,还支持其他格式(如HTML、XML)的转换。
缺点:


  • 商业允许: iText 7 是商业软件,某些高级功能须要购买允许证。
  • 学习曲线: API较为复杂,大概须要肯定的学习本钱。
性能:


  • 对于大多数应用场景来说,iText 的性能是富足的。它在内存管理和文件处理惩罚速率方面表现精良,尤其适当处理惩罚复杂的PDF文档。
实用场景:


  • 适当须要天生复杂PDF文档的应用,尤其是那些涉及安全性和高级功能的企业级应用。
示例代码:
  1. <!-- 添加依赖 -->
  2. <dependency>
  3.     <groupId>com.itextpdf</groupId>
  4.     <artifactId>itext7-core</artifactId>
  5.     <version>7.1.15</version> <!-- 请检查并使用最新版本 -->
  6. </dependency>
  7. import com.itextpdf.kernel.pdf.PdfDocument;
  8. import com.itextpdf.kernel.pdf.PdfWriter;
  9. import com.itextpdf.layout.Document;
  10. import com.itextpdf.layout.element.Paragraph;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. public class ITextPdfService {
  14.     public void export(HttpServletResponse response) throws IOException {
  15.         // 设置响应头
  16.         response.setContentType("application/pdf");
  17.         response.setHeader("Content-Disposition", "attachment; filename=users.pdf");
  18.         try (PdfWriter writer = new PdfWriter(response.getOutputStream());
  19.              PdfDocument pdf = new PdfDocument(writer);
  20.              Document document = new Document(pdf)) {
  21.             // 添加内容到PDF
  22.             document.add(new Paragraph("Hello, this is a PDF document created with iText in Spring Boot!"));
  23.             // 关闭文档
  24.             document.close();
  25.         }
  26.     }
  27. }
复制代码

2. Apache PDFBox

长处:


  • 完全开源: 没有商业限定,适当全部范例的项目。
  • 轻量级: 依靠项较少,项目结构简便。
  • 易于上手: API相对简单,适当快速开辟和学习。
缺点:


  • 功能有限: 在一些复杂的功能上,如处理惩罚大型PDF或实行高级操纵,大概不如iText强盛。
  • 性能题目: 在处理惩罚非常大的文件或高并发场景下,性能大概会略逊于iText。
性能:


  • PDFBox 在处理惩罚较小的PDF文件时表现精良,但在处理惩罚大文件大概高并发场景下,其性能大概会略逊于iText。
实用场景:


  • 适当须要天生简单PDF文档的应用,尤其是那些渴望保持完全开源的项目。
示例代码:
  1. <!-- 添加依赖 -->
  2. <dependency>
  3.     <groupId>org.apache.pdfbox</groupId>
  4.     <artifactId>pdfbox</artifactId>
  5.     <version>2.0.27</version> <!-- 请检查并使用最新版本 -->
  6. </dependency>
  7. import org.apache.pdfbox.pdmodel.PDDocument;
  8. import org.apache.pdfbox.pdmodel.PDPage;
  9. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  10. import org.apache.pdfbox.pdmodel.font.PDType1Font;
  11. import javax.servlet.http.HttpServletResponse;
  12. import java.io.IOException;
  13. public class PdfBoxPdfService {
  14.     public void export(HttpServletResponse response) throws IOException {
  15.         // 设置响应头
  16.         response.setContentType("application/pdf");
  17.         response.setHeader("Content-Disposition", "attachment; filename=users.pdf");
  18.         try (PDDocument document = new PDDocument()) {
  19.             PDPage page = new PDPage();
  20.             document.addPage(page);
  21.             try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
  22.                 contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
  23.                 contentStream.beginText();
  24.                 contentStream.newLineAtOffset(100, 700);
  25.                 contentStream.showText("Hello, this is a PDF document created with Apache PDFBox in Spring Boot!");
  26.                 contentStream.endText();
  27.             }
  28.             // 将PDF写入响应输出流
  29.             document.save(response.getOutputStream());
  30.         }
  31.     }
  32. }
复制代码

3. JasperReports

长处:


  • 强盛的报表筹划本领: 支持复杂的表格、图表、分组、子报表等功能。
  • 多数据源支持: 可以从数据库、JavaBean聚集、CSV、XML等多种数据源获取数据。
  • 丰富的样式和格式化: 支持多种字体、颜色、边框、配景等样式设置,以及日期、数字等格式化。
  • 集成度高: 与Spring Boot集成方便,可以轻松地将报表天生逻辑嵌入到应用步调中。
  • 输特别式多样: 除了PDF,还支持HTML、Excel、CSV等多种输特别式。
缺点:


  • 学习曲线较陡: JRXML模板语法较为复杂,须要肯定时间来把握。
  • 依靠项较多: 须要引入多个依靠项,大概会增长项目的复杂度。
  • 性能题目: 在处理惩罚非常大的数据集时,大概会碰到性能瓶颈,尤其是在内存管理和渲染速率方面。
性能:


  • 在处理惩罚复杂报表和大数据集时表现较好,尤其是在须要高级功能(如分组、图表)的情况下。
实用场景:


  • 适当须要天生复杂报表的应用,尤其是包罗大量数据、图表、分组等元素的场景。
  • 适当须要支持多种输特别式的应用。
示例代码:
  1. <!-- 添加依赖 -->
  2. <dependency>
  3.     <groupId>net.sf.jasperreports</groupId>
  4.     <artifactId>jasperreports</artifactId>
  5.     <version>6.17.0</version> <!-- 请检查并使用最新版本 -->
  6. </dependency>
  7. import net.sf.jasperreports.engine.*;
  8. import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
  9. import org.springframework.web.bind.annotation.GetMapping;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.io.InputStream;
  14. import java.util.HashMap;
  15. import java.util.List;
  16. import java.util.Map;
  17. @RestController
  18. @RequestMapping("/api")
  19. public class JasperReportController {
  20.     @GetMapping("/export-jasper-pdf")
  21.     public void export(HttpServletResponse response) throws Exception {
  22.         // 设置响应头
  23.         response.setContentType("application/pdf");
  24.         response.setHeader("Content-Disposition", "attachment; filename=report.pdf");
  25.         // 加载JRXML模板
  26.         InputStream reportTemplate = getClass().getResourceAsStream("/templates/report.jrxml");
  27.         JasperReport jasperReport = JasperCompileManager.compileReport(reportTemplate);
  28.         // 准备数据
  29.         List<User> users = userService.getAllUsers(); // 假设有一个UserService类
  30.         JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(users);
  31.         // 设置参数
  32.         Map<String, Object> parameters = new HashMap<>();
  33.         parameters.put("title", "User Report");
  34.         // 生成PDF
  35.         JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
  36.         JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
  37.     }
  38. }
复制代码

4. Thymeleaf + Flying Saucer

长处:


  • HTML/CSS友爱: 使用尺度的HTML和CSS举行页面结构和样式设置,非常适当前端开辟职员。
  • 易于维护: HTML模板容易明确和修改,尤其适当那些已经认识HTML/CSS的团队。
  • 机动性高: 可以轻松地将现有的Thymeleaf模板转换为PDF,淘汰了重复工作。
  • 轻量级: 相对于JasperReports,Flying Saucer的依靠项较少,项目结构更简便。
  • 快速开辟: 对于简单的PDF天生需求,开辟速率较快,由于不须要学习新的模板语言。
缺点:


  • 功能有限: 相比JasperReports,Flying Saucer的功能较为有限,特别是在处理惩罚复杂报表(如分组、图表)时。
  • 性能一样寻常: 在处理惩罚大文件或高并发场景下,性能大概不如JasperReports。
  • 样式兼容性: 某些CSS样式大概无法完全兼容,导致PDF渲染结果与预期不符。
性能:


  • 对于简单的PDF天生需求,性能富足,而且开辟速率快,维护本钱低。
实用场景:


  • 适当须要将现有的HTML页面转换为PDF的应用,尤其是那些已经有现成的HTML模板的情况。
  • 适当天生简单的文档,如发票、条约、陈诉等,而不涉及复杂的报表功能。
示例代码:
  1. <!-- 添加依赖 -->
  2. <dependency>
  3.     <groupId>org.thymeleaf</groupId>
  4.     <artifactId>thymeleaf</artifactId>
  5.     <version>3.0.12.RELEASE</version> <!-- 请检查并使用最新版本 -->
  6. </dependency>
  7. <dependency>
  8.     <groupId>org.xhtmlrenderer</groupId>
  9.     <artifactId>flying-saucer-pdf-itext5</artifactId>
  10.     <version>9.1.20</version> <!-- 请检查并使用最新版本 -->
  11. </dependency>
  12. import org.springframework.core.io.ClassPathResource;
  13. import org.springframework.ui.Model;
  14. import org.springframework.web.bind.annotation.GetMapping;
  15. import org.springframework.web.bind.annotation.RequestMapping;
  16. import org.springframework.web.bind.annotation.RestController;
  17. import org.thymeleaf.TemplateEngine;
  18. import org.thymeleaf.context.Context;
  19. import org.xhtmlrenderer.pdf.ITextRenderer;
  20. import javax.servlet.http.HttpServletResponse;
  21. import java.io.InputStream;
  22. import java.io.InputStreamReader;
  23. import java.io.OutputStream;
  24. import java.nio.charset.StandardCharsets;
  25. @RestController
  26. @RequestMapping("/api")
  27. public class PdfController {
  28.     private final TemplateEngine templateEngine;
  29.     public PdfController(TemplateEngine templateEngine) {
  30.         this.templateEngine = templateEngine;
  31.     }
  32.     @GetMapping("/export-thymeleaf-pdf")
  33.     public void export(HttpServletResponse response) throws Exception {
  34.         // 设置响应头
  35.         response.setContentType("application/pdf");
  36.         response.setHeader("Content-Disposition", "attachment; filename=report.pdf");
  37.         // 加载HTML模板
  38.         InputStream templateInputStream = new ClassPathResource("templates/report.html").getInputStream();
  39.         String htmlContent = new String(templateInputStream.readAllBytes(), StandardCharsets.UTF_8);
  40.         // 准备上下文数据
  41.         Context context = new Context();
  42.         context.setVariable("users", userService.getAllUsers()); // 假设有一个UserService类
  43.         context.setVariable("title", "User Report");
  44.         // 渲染HTML
  45.         String processedHtml = templateEngine.process(htmlContent, context);
  46.         // 将HTML转换为PDF
  47.         ITextRenderer renderer = new ITextRenderer();
  48.         renderer.setDocumentFromString(processedHtml);
  49.         renderer.layout();
  50.         // 输出PDF
  51.         try (OutputStream outputStream = response.getOutputStream()) {
  52.             renderer.createPDF(outputStream);
  53.         }
  54.     }
  55. }
复制代码

性能与易用性对比

特性
iText
Apache PDFBox
JasperReports
Thymeleaf + Flying Saucer
性能
高
中
高(复杂报表)
中(简单文档)
易用性
复杂
简单
复杂
简单
功能
强盛
有限
非常强盛(报表)
有限(HTML/CSS)
依靠项
较多(部分需商业允许)
少
较多
少
实用场景
复杂PDF文档
简单PDF文档
复杂报表
简单文档/HTML转PDF
学习曲线
陡峭
平缓
陡峭
平缓

总结


  • 选择 iText 如果你须要天生复杂的PDF文档,尤其是涉及到安全性和高级功能的企业级应用。iText 提供了最全面的功能和最佳的性能,但须要留意其商业允许要求。
  • 选择 Apache PDFBox 如果你渴望保持完全开源,而且只须要天生简单的PDF文档。PDFBox 轻量级且易于上手,适当小型项目或对性能要求不高的场景。
  • 选择 JasperReports 如果你须要天生复杂的报表,特别是涉及到分组、图表、子报表等功能。JasperReports 是一个功能强盛且成熟的工具,适当企业级应用。
  • 选择 Thymeleaf + Flying Saucer 如果你须要将现有的HTML页面转换为PDF,大概只须要天生简单的文档(如发票、条约等)。它易于使用,开辟速率快,特别适当前端开辟职员。
在现实项目中,发起根据具体需求和技能栈选择符合的工具。如果你不确定哪种工具更适当,可以先实行一个小规模的原型项目,评估其性能和易用性,再做终极决定。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表