使用 Spring Boot + OpenPdf 实现 PDF 导出功能

原创 编程疏影 路条编程 2024年07月28日 08:01 河北

图片

使用 Spring Boot + OpenPdf 实现 PDF 导出功能

在当今的 Web 应用开发中,经常需要实现数据的导出功能,其中 PDF 格式由于其良好的通用性和可读性而被广泛使用。本文将详细介绍如何使用 Spring Boot 结合 OpenPdf 库来实现 PDF 导出功能。

项目创建及依赖配置(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>pdf-export-system</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>PDF Export System</name>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.openpdf</groupId>
            <artifactId>openpdf</artifactId>
            <version>1.3.27</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

配置文件(application.yml)

server:
  port: 8080

数据表 DDL 示例(假设为订单表)

CREATE TABLE `orders` (
    `id` INT AUTO_INCREMENT PRIMARY KEY,
    `order_number` VARCHAR(255),
    `customer_name` VARCHAR(255),
    `total_price` DECIMAL(10, 2)
);

配置类

package com.example.config;

import com.openpdf.apis.FontProgram;
import com.openpdf.apis.FontProgramFactory;
import com.openpdf.apis.io.ResourceFontSource;
import com.openpdf.data.BaseFont;
import com.openpdf.layout.Document;
import com.openpdf.layout.Style;
import com.openpdf.layout.element.Paragraph;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
public class PdfConfig {

    @Bean
    public FontProgram fontProgram() throws IOException {
        // 加载字体文件
        ResourceFontSource fontSource = new ResourceFontSource("/fonts/simhei.ttf");
        return FontProgramFactory.createFontProgram(fontSource);
    }

    @Bean
    public BaseFont baseFont() throws IOException {
        FontProgram fontProgram = fontProgram();
        return BaseFont.createFont(fontProgram, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
    }

    @Bean
    public Style defaultStyle(BaseFont baseFont) {
        Style style = new Style();
        style.setFont(baseFont);
        style.setFontSize(12);
        return style;
    }
}

服务类

Java 类模板

package com.example.service;

import com.example.config.PdfConfig;
import com.openpdf.data.BaseFont;
import com.openpdf.layout.Document;
import com.openpdf.layout.element.Paragraph;
import com.openpdf.layout.element.Table;
import com.openpdf.layout.properties.TextAlignment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

@Service
public class PdfExportService {

    @Autowired
    private PdfConfig pdfConfig;

    public byte[] exportPdf() throws IOException {
        BaseFont baseFont = pdfConfig.baseFont();

        Document document = new Document();

        Paragraph title = new Paragraph("订单列表", pdfConfig.defaultStyle(baseFont));
        title.setTextAlignment(TextAlignment.CENTER);
        document.add(title);

        Table table = new Table(4);
        table.addCell("订单号");
        table.addCell("客户姓名");
        table.addCell("总价");

        // 模拟从数据库获取订单数据
        table.addCell("ORD001");
        table.addCell("张三");
        table.addCell("100.00");

        document.add(table);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.writeTo(outputStream);

        return outputStream.toByteArray();
    }
}

Html 模板

package com.example.service;

import com.example.config.PdfConfig;
import com.openpdf.data.BaseFont;
import com.openpdf.layout.Document;
import com.openpdf.layout.element.Paragraph;
import com.openpdf.layout.element.Table;
import com.openpdf.layout.properties.TextAlignment;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

@Service
public class PdfExportService {

    @Autowired
    private PdfConfig pdfConfig;

    @Autowired
    private VelocityEngine velocityEngine;

    public byte[] exportPdf() throws IOException {
        BaseFont baseFont = pdfConfig.baseFont();

        // 从 HTML 模板生成内容
        Template template = velocityEngine.getTemplate("templates/pdf-template.vm");
        VelocityContext context = new VelocityContext();
        // 向上下文添加数据
        Map<String, Object> data = new HashMap<>();
        data.put("orders", getOrders());
        context.put("data", data);

        StringWriter writer = new StringWriter();
        template.merge(context, writer);

        Document document = new Document();
        Paragraph title = new Paragraph("订单列表", pdfConfig.defaultStyle(baseFont));
        title.setTextAlignment(TextAlignment.CENTER);
        document.add(title);

        // 将生成的 HTML 内容添加到 PDF 中
        document.add(new Paragraph(writer.toString(), pdfConfig.defaultStyle(baseFont)));

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        document.writeTo(outputStream);

        return outputStream.toByteArray();
    }

    private List<Order> getOrders() {
        // 模拟从数据库获取订单数据
        List<Order> orders = new ArrayList<>();
        orders.add(new Order("ORD001", "张三", 100.00));
        return orders;
    }
}

HTML 模板(pdf-template.vm)

<!DOCTYPE html>
<html>
<head>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
    </style>
</head>
<body>
    <h2>订单详情</h2>
    <table border="1">
        <tr>
            <th>订单号</th>
            <th>客户姓名</th>
            <th>总价</th>
        </tr>
        #foreach($order in $data.orders)
        <tr>
            <td>$order.orderNumber</td>
            <td>$order.customerName</td>
            <td>$order.totalPrice</td>
        </tr>
        #end
    </table>
</body>
</html>

控制器类

package com.example.controller;

import com.example.service.PdfExportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;

@RestController
@RequestMapping("/pdf")
public class PdfController {

    @Autowired
    private PdfExportService pdfExportService;

    @GetMapping(value = "/export", produces = MediaType.APPLICATION_PDF_VALUE)
    public ResponseEntity<byte[]> exportPdf() throws IOException {
        byte[] pdfBytes = pdfExportService.exportPdf();
        return ResponseEntity.ok()
              .header("Content-Disposition", "attachment; filename=orders.pdf")
              .body(pdfBytes);
    }
}
  • 通过以上步骤,我们成功地使用 Spring Boot 结合 OpenPdf 实现了具有使用 HTML 模板配置导出格式功能的 PDF 导出。

    💪 优势:

    🔍 考虑因素:

    希望本文能够帮助您在实际项目中顺利实现具有丰富格式配置的 PDF 导出功能。

    • 模板的正确性和兼容性,确保生成的 HTML 在 PDF 中能够正确呈现。

    • 对模板中的数据进行适当的验证和处理,防止异常情况。

    • 利用 HTML 模板能够更灵活地控制 PDF 的布局和样式。

    • 结合 Velocity 模板引擎,实现数据与模板的动态结合。

总结

本文详细介绍了如何使用 Spring Boot 结合 OpenPdf 和 Velocity 模板引擎来实现具有灵活格式配置的 PDF 导出功能。通过创建项目依赖、配置文件、数据表、Order 类、配置类、服务类、控制器类以及 HTML 模板,实现了从数据获取、模板渲染到 PDF 生成的完整流程。在实际应用中,开发人员可以根据具体的业务需求进一步定制模板和数据处理逻辑,以满足不同的 PDF 导出需求。

今天就讲到这里,如果有问题需要咨询,大家可以直接留言或扫下方二维码来知识星球找我,我们会尽力为你解答。

图片

AI资源聚合站已经正式上线,该平台不仅仅是一个AI资源聚合站,更是一个为追求知识深度和广度的人们打造的智慧聚集地。通过访问 AI 资源聚合网站 https://ai-ziyuan.techwisdom.cn/,你将进入一个全方位涵盖人工智能和语言模型领域的宝藏库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值