【Spring Boot 实现 PDF 导出】

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文档的应用,尤其是那些涉及安全性和高级功能的企业级应用。

示例代码:

<!-- 添加依赖 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.1.15</version> <!-- 请检查并使用最新版本 -->
</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 {
        // 设置响应头
        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)) {

            // 添加内容到PDF
            document.add(new Paragraph("Hello, this is a PDF document created with iText in Spring Boot!"));

            // 关闭文档
            document.close();
        }
    }
}

2. Apache PDFBox

优点:

  • 完全开源: 没有商业限制,适合所有类型的项目。
  • 轻量级: 依赖项较少,项目结构简洁。
  • 易于上手: API相对简单,适合快速开发和学习。

缺点:

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

性能:

  • PDFBox 在处理较小的PDF文件时表现良好,但在处理大文件或者高并发场景下,其性能可能会略逊于iText。

适用场景:

  • 适合需要生成简单PDF文档的应用,尤其是那些希望保持完全开源的项目。

示例代码:

<!-- 添加依赖 -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.27</version> <!-- 请检查并使用最新版本 -->
</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 {
        // 设置响应头
        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写入响应输出流
            document.save(response.getOutputStream());
        }
    }
}

3. JasperReports

优点:

  • 强大的报表设计能力: 支持复杂的表格、图表、分组、子报表等功能。
  • 多数据源支持: 可以从数据库、JavaBean集合、CSV、XML等多种数据源获取数据。
  • 丰富的样式和格式化: 支持多种字体、颜色、边框、背景等样式设置,以及日期、数字等格式化。
  • 集成度高: 与Spring Boot集成方便,可以轻松地将报表生成逻辑嵌入到应用程序中。
  • 输出格式多样: 除了PDF,还支持HTML、Excel、CSV等多种输出格式。

缺点:

  • 学习曲线较陡: JRXML模板语法较为复杂,需要一定时间来掌握。
  • 依赖项较多: 需要引入多个依赖项,可能会增加项目的复杂度。
  • 性能问题: 在处理非常大的数据集时,可能会遇到性能瓶颈,尤其是在内存管理和渲染速度方面。

性能:

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

适用场景:

  • 适合需要生成复杂报表的应用,尤其是包含大量数据、图表、分组等元素的场景。
  • 适合需要支持多种输出格式的应用。

示例代码:

<!-- 添加依赖 -->
<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.17.0</version> <!-- 请检查并使用最新版本 -->
</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 {
        // 设置响应头
        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);

        // 准备数据
        List<User> users = userService.getAllUsers(); // 假设有一个UserService类
        JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(users);

        // 设置参数
        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

优点:

  • HTML/CSS友好: 使用标准的HTML和CSS进行页面布局和样式设置,非常适合前端开发人员。
  • 易于维护: HTML模板容易理解和修改,尤其适合那些已经熟悉HTML/CSS的团队。
  • 灵活性高: 可以轻松地将现有的Thymeleaf模板转换为PDF,减少了重复工作。
  • 轻量级: 相对于JasperReports,Flying Saucer的依赖项较少,项目结构更简洁。
  • 快速开发: 对于简单的PDF生成需求,开发速度较快,因为不需要学习新的模板语言。

缺点:

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

性能:

  • 对于简单的PDF生成需求,性能足够,并且开发速度快,维护成本低。

适用场景:

  • 适合需要将现有的HTML页面转换为PDF的应用,尤其是那些已经有现成的HTML模板的情况。
  • 适合生成简单的文档,如发票、合同、报告等,而不涉及复杂的报表功能。

示例代码:

<!-- 添加依赖 -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.12.RELEASE</version> <!-- 请检查并使用最新版本 -->
</dependency>
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-itext5</artifactId>
    <version>9.1.20</version> <!-- 请检查并使用最新版本 -->
</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 {
        // 设置响应头
        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);

        // 准备上下文数据
        Context context = new Context();
        context.setVariable("users", userService.getAllUsers()); // 假设有一个UserService类
        context.setVariable("title", "User Report");

        // 渲染HTML
        String processedHtml = templateEngine.process(htmlContent, context);

        // 将HTML转换为PDF
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocumentFromString(processedHtml);
        renderer.layout();

        // 输出PDF
        try (OutputStream outputStream = response.getOutputStream()) {
            renderer.createPDF(outputStream);
        }
    }
}

性能与易用性对比

特性iTextApache PDFBoxJasperReportsThymeleaf + Flying Saucer
性能高(复杂报表)中(简单文档)
易用性复杂简单复杂简单
功能强大有限非常强大(报表)有限(HTML/CSS)
依赖项较多(部分需商业许可)较多
适用场景复杂PDF文档简单PDF文档复杂报表简单文档/HTML转PDF
学习曲线陡峭平缓陡峭平缓

总结

  • 选择 iText 如果你需要生成复杂的PDF文档,尤其是涉及到安全性和高级功能的企业级应用。iText 提供了最全面的功能和最佳的性能,但需要注意其商业许可要求。

  • 选择 Apache PDFBox 如果你希望保持完全开源,并且只需要生成简单的PDF文档。PDFBox 轻量级且易于上手,适合小型项目或对性能要求不高的场景。

  • 选择 JasperReports 如果你需要生成复杂的报表,特别是涉及到分组、图表、子报表等功能。JasperReports 是一个功能强大且成熟的工具,适合企业级应用。

  • 选择 Thymeleaf + Flying Saucer 如果你需要将现有的HTML页面转换为PDF,或者只需要生成简单的文档(如发票、合同等)。它易于使用,开发速度快,特别适合前端开发人员。

在实际项目中,建议根据具体需求和技术栈选择合适的工具。如果你不确定哪种工具更适合,可以先尝试一个小规模的原型项目,评估其性能和易用性,再做最终决定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/946746.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端-动画库Lottie 3分钟学会使用

目录 1. Lottie地址 2. 使用html实操 3. 也可以选择其他的语言 1. Lottie地址 LottieFiles: Download Free lightweight animations for website & apps.Effortlessly bring the smallest, free, ready-to-use motion graphics for the web, app, social, and designs.…

汇编环境搭建

学习视频 将MASM所在目录 指定为C盘

Flutter:打包apk,详细图文介绍(一)

困扰了一天&#xff0c;终于能正常打包apk安装了&#xff0c;记录下打包的流程。建议参考我这篇文章时&#xff0c;同时看下官网的构建说明。 官网构建并发布 Android 应用详情 1、AS创建Flutter项目 2、cmd执行命令 生成一个sunluyi.jks的文件&#xff0c;可以自行把sunluyi替…

单个变量a的妙用

一道清华大学复试上机题 问题&#xff1a;为什么只需要定义一个整数变量a&#xff0c;而不是定义一个数组a[]&#xff1f; 回答 在这段代码中&#xff0c;只需要定义一个整数变量 a&#xff0c;而不是一个数组 a[]&#xff0c;是因为程序的逻辑是逐个处理输入的整数并立即输出…

【YOLOv8模型网络结构图理解】

YOLOv8模型网络结构图理解 1 YOLOv8的yaml配置文件2 YOLOv8网络结构2.1 Conv2.2 C3与C2f2.3 SPPF2.4 Upsample2.5 Detect层 1 YOLOv8的yaml配置文件 YOLOv8的配置文件定义了模型的关键参数和结构&#xff0c;包括类别数、模型尺寸、骨干&#xff08;backbone&#xff09;和头部…

手机租赁平台开发助力智能设备租赁新模式

内容概要 手机租赁平台开发&#xff0c;简单说就是让你用得起高大上的智能设备&#xff0c;不管是最新款的手机、平板&#xff0c;还是那些炫酷的智能耳机&#xff0c;这个平台应有尽有。想要体验但又不希望花大钱&#xff1f;那你就找对地方了&#xff01;通过灵活的租赁方案…

「Mac畅玩鸿蒙与硬件48」UI互动应用篇25 - 简易购物车功能实现

本篇教程将带你实现一个简易购物车功能。通过使用接口定义商品结构&#xff0c;我们将创建一个动态购物车&#xff0c;支持商品的添加、移除以及实时总价计算。 关键词 UI互动应用接口定义购物车功能动态计算商品管理列表操作 一、功能说明 简易购物车功能包含以下交互&#…

Datawhale AI冬令营(第二期)动手学AI Agent task2--学Prompt工程,优化Agent效果

目录 如何写好Prompt&#xff1f; 工具包神器1&#xff1a;Prompt框架——CO-STAR 框架 工具包神器2&#xff1a;Prompt结构优化 工具包神器3&#xff1a;引入案例 案例&#xff1a;构建虚拟女友小冰 1. 按照 CO-STAR框架 梳理目标 2. 撰写Prompt 3. 制作对话生成应用&…

SpringBoot整合springmvc

文章目录 1.SpringMVC的自动管理1.1中央转发器1.1.1Spring boot配置多个DispatcherServlet 1.2控制器1.2.1找到启动类的位置1.2.1.1SpringApplication.run()1.2.1.2SpringApplication 构造方法1.2.1.3deduceMainApplicationClass() 1.2.2ComponentScan 注解 1.3视图解析器自动管…

常见的排序算法过程和比较分析

比较分析 排序类别排序算法时间复杂度&#xff08;最好&#xff09;时间复杂度&#xff08;最坏&#xff09;时间复杂度&#xff08;平均&#xff09;辅助空间复杂度稳定性插入排序直接插入排序O(n)O(n)O(n)O(1)稳定插入排序折半插入排序O(n)O(n)O(n)O(1)稳定插入排序希尔排序…

[MySQL报错]关于发生net start mysql 服务无法启动,服务没有报告任何错误的五种解决方案。

咋直接进入主题。 我遇到的问题是net start mysql 服务无法启动&#xff0c;服务没有报告任何错误 其问题出在哪里呢 一.ini文件配置问题 在于你没有给你下载好的mysql文件中配置.ini文件。 该如何配置呢。那就是先在文件夹中创建一个文本文件&#xff0c;把下面内容复制进去…

Unity网络通信相关

Socket 通信一张图搞定 谁提供服务谁绑定端口&#xff0c;建立Listener,写Host

小波与傅里叶变换在去噪效果上的对比分析-附Matlab源程序

&#x1f468;‍&#x1f393; 博主简介&#xff1a;博士研究生 &#x1f52c; 超级学长&#xff1a;超级学长实验室&#xff08;提供各种程序开发、实验复现与论文指导&#xff09; &#x1f4e7; 个人邮箱&#xff1a;easy_optics126.com &#x1f56e; 目 录 摘要一、…

如何利用 ClickHouse 实现高级分析:MySQL 到 ClickHouse 实时数据同步指南

在数据驱动的时代&#xff0c;企业必须依靠先进的数据分析能力来提升竞争力。随着数据量的激增和业务需求的复杂化&#xff0c;传统的关系型数据库已经无法满足高效处理和实时分析的需求。ClickHouse 作为一款高性能的列式数据库&#xff0c;凭借其卓越的查询性能和可扩展性&am…

计算机网络 (12)物理层下面的传输媒体

前言 计算机网络物理层下面的传输媒体是计算机网络设备之间的物理通路&#xff0c;也称为传输介质或传输媒介&#xff0c;并不包含在计算机网络体系结构中&#xff0c;而是处于物理层之下。 一、传输媒体的分类 导向型媒体&#xff1a;电磁波被导引沿着固体媒体传播。常见的导向…

rouyi(前后端分离版本)配置

从gitee上下载&#xff0c;复制下载地址&#xff0c;到 点击Clone&#xff0c;下载完成&#xff0c; 先运行后端&#xff0c;在运行前端 运行后端&#xff1a; 1.配置数据库&#xff0c;在Navicat软件中&#xff0c;连接->mysql->名字自己起(rouyi-vue-blog),用户名roo…

深度学习在光学成像中是如何发挥作用的?

深度学习在光学成像中的作用主要体现在以下几个方面&#xff1a; 1. **图像重建和去模糊**&#xff1a;深度学习可以通过优化图像重建算法来处理模糊图像或降噪&#xff0c;改善成像质量。这涉及到从低分辨率图像生成高分辨率图像&#xff0c;突破传统光学系统的分辨率限制。 …

svn不能添加.a文件

解决办法 在home目录下有一个.subversion文件夹&#xff0c;文件夹内有个config文件&#xff0c;里面可以修改过滤的文件类型 在使用命令svn add的时候带上参数–no-ignore&#xff0c;这样就会不顾config中的规则&#xff0c;将指定路径的文件都添加到版本库中 rockyrocky:/e…

【蓝桥杯选拔赛真题87】python输出字符串 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析

目录 python输出字符串 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python输出字符串 第十五届蓝桥杯青少年组python比赛选拔赛真题详细解析…

基于SpringBoot的题库管理系统的设计与实现(源码+SQL+LW+部署讲解)

文章目录 摘 要1. 第1章 选题背景及研究意义1.1 选题背景1.2 研究意义1.3 论文结构安排 2. 第2章 相关开发技术2.1 前端技术2.2 后端技术2.3 数据库技术 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系统需求分析 4. 第4章 系统概要设计4.1 系统功能模块设计4.2 数据库设计 5.…