原创 编程疏影 路条编程 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/,你将进入一个全方位涵盖人工智能和语言模型领域的宝藏库。