Java將數(shù)據(jù)寫入到PDF文件的操作步驟
說明:業(yè)務(wù)中有時會有將系統(tǒng)數(shù)據(jù)寫入到PDF文件中,生成一份報告文件的場景,本文介紹如何實現(xiàn)。
安裝應(yīng)用
在寫代碼前,先安裝一個生成PDF的工具,是開源的,在 Github 上,地址:
https://github.com/wkhtmltopdf/wkhtmltopdf/releases
我在 windows 系統(tǒng)上演示,就下載下面這個版本,后面部署測試/線上環(huán)境也可以下對應(yīng)的版本,在服務(wù)器上部署。

下載下來后,如下,是一個可執(zhí)行程序

雙擊安裝

安裝到系統(tǒng)上一個沒有中文,沒有空格的路徑下

Demo
寫一個 demo,創(chuàng)建一個 Maven 項目
第一步:引入依賴
引入相關(guān)依賴,繼承 Spring boot,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 http://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>2.7.12</version>
<relativePath/>
</parent>
<groupId>com.hezy</groupId>
<artifactId>pdf_demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- web依賴,用調(diào)用接口的方式來測試 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 生成pdf依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.github.jhonnymertz</groupId>
<artifactId>java-wkhtmltopdf-wrapper</artifactId>
<version>1.3.1-RELEASE</version>
</dependency>
<!-- lombok依賴 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<!-- 編譯插件,定義編譯語言,后面用于構(gòu)建PDF文件byte[],返回給前端 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
需要注意的是,spring-boot-starter-thymeleaf 不要指定版本,不然會報啟動錯誤,詳細(xì)看下面:
啟動項目,報下面這個異常
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2025-10-23 22:28:23.811 ERROR 11536 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPLICATION FAILED TO START *************************** Description: A component required a bean of type 'org.thymeleaf.TemplateEngine' that could not be found. Action: Consider defining a bean of type 'org.thymeleaf.TemplateEngine' in your configuration.
as follows:

解決
thymeleaf 版本與 Spring Boot 版本不匹配

不要指定thymeleaf 版本,讓它用 Spring Boot 指定的

通過下面的步驟,可以查看 Spring Boot 管理的依賴版本

第二步:配置文件
添加相關(guān)配置到 application.yml 中,如下:
spring:
thymeleaf:
prefix: classpath:/template/
suffix: .html
mode: HTML
cache: false # 關(guān)閉緩存
wkhtmltopdf:
exec: D:\dev\wkhtmltopdf\bin\wkhtmltopdf.exe
這里面定義了后面 PDF 填充的模板(靜態(tài)資源)的路徑,和前面下載的 PDF 轉(zhuǎn)換工具在系統(tǒng)中的安裝路徑。
第三步:創(chuàng)建模板
創(chuàng)建一個 PDF 填充模板,內(nèi)容如下,填充數(shù)據(jù)用 ${對象名.屬性名} 占位,語法應(yīng)該和 FreeMaker 差不多
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>${data.title}</title>
</head>
<body>
<div>姓名:</div> <div th:text="${data.name}"></div>
<div>年齡:</div> <div th:text="${data.age}"></div>
<div>性別:</div> <div th:text="${data.sex}"></div>
</body>
</html>
頁面打開如下:

注意一下模板所在位置,需要和前面配置文件中指定的保持一致

第四步:寫代碼
寫一個接口,接口 做兩件事,1)組裝 PDF 中所需要的數(shù)據(jù);2)合成 PDF 文件,返回前端
(Controller)
import com.hezy.service.PDFService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@RestController
public class PDFController {
@Resource
private PDFService pdfService;
@PostMapping("/pdf")
public byte[] pdf() {
// 構(gòu)建響應(yīng)頭
String fileName = "example.pdf";
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", encodedFileName);
// 返回
return ResponseEntity.ok()
.headers(headers)
.body(pdfService.pdf()).getBody();
}
}
(Service 實現(xiàn)類)
import com.github.jhonnymertz.wkhtmltopdf.wrapper.Pdf;
import com.github.jhonnymertz.wkhtmltopdf.wrapper.configurations.WrapperConfig;
import com.github.jhonnymertz.wkhtmltopdf.wrapper.objects.SourceType;
import com.github.jhonnymertz.wkhtmltopdf.wrapper.params.Param;
import com.hezy.pojo.PDFDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import javax.annotation.Resource;
@Service
public class PDFServiceImpl implements PDFService {
@Value("${spring.wkhtmltopdf.exec:}")
private String wkhtmltopdfPath;
@Resource
private TemplateEngine templateEngine;
@Override
public byte[] pdf() {
try {
// 1.創(chuàng)建上下文
Context context = new Context();
WrapperConfig config = new WrapperConfig(wkhtmltopdfPath);
// 2.創(chuàng)建PDF生成器
Pdf pdf = new Pdf(config);
// 3.填充數(shù)據(jù)
PDFDTO pdfdto = new PDFDTO("Hello World", "張三", "男", "18");
context.setVariable("data", pdfdto);
// 4.指定模板,這里只需指定名稱,模板所在路徑、模板后綴名都在配置文件中設(shè)置過了
String htmlContent = templateEngine.process("template", context);
pdf.addPage(htmlContent, SourceType.htmlAsString);
// 5.配置 PDF 文件的通用參數(shù)
pdf.addParam(new Param("--page-size", "A4"),
new Param("--margin-top", "15mm"),
new Param("--margin-bottom", "15mm"),
new Param("--margin-left", "15mm"),
new Param("--margin-right", "15mm"),
new Param("--enable-local-file-access"),
new Param("--disable-smart-shrinking"),
new Param("--print-media-type"),
new Param("--encoding", "UTF-8"));
// 6.生成PDF
return pdf.getPDF();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
第五步:啟動測試
啟動項目,調(diào)用接口,返回字節(jié)數(shù)組

保存為 PDF 文件,打開如下,數(shù)據(jù)內(nèi)容已填充到 PDF 文件里

OKKK,現(xiàn)在就是進(jìn)一步完成細(xì)節(jié),一邊根據(jù)業(yè)務(wù)需求,完善 PDF 的內(nèi)容、結(jié)構(gòu)和樣式,修改/增加模板文件,一邊在后端代碼里完善獲取數(shù)據(jù)的邏輯。
總結(jié)
本文介紹了在 Java 中如何將數(shù)據(jù)寫入到 PDF 文件中。
以上就是Java將數(shù)據(jù)寫入到PDF文件的操作步驟的詳細(xì)內(nèi)容,更多關(guān)于Java數(shù)據(jù)寫入PDF的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot+Prometheus+Grafana實現(xiàn)應(yīng)用監(jiān)控和報警的詳細(xì)步驟
這篇文章主要介紹了SpringBoot+Prometheus+Grafana實現(xiàn)應(yīng)用監(jiān)控和報警的詳細(xì)步驟,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
SpringMVC?RESTFul實體類創(chuàng)建及環(huán)境搭建
這篇文章主要為大家介紹了SpringMVC?RESTFul實體類創(chuàng)建及環(huán)境搭建詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
Java中數(shù)組轉(zhuǎn)換為列表的兩種實現(xiàn)方式(超簡單)
本文介紹了在Java中將數(shù)組轉(zhuǎn)換為列表的兩種常見方法使用Arrays.asList和Java8的Stream API,Arrays.asList方法簡單易用,但返回的列表是固定大小的;而使用Stream API可以實現(xiàn)更靈活的操作,如過濾和映射,根據(jù)具體需求選擇合適的方法,感興趣的朋友一起看看吧2025-03-03
springboot?整合?clickhouse的實現(xiàn)示例
本文主要介紹了springboot?整合?clickhouse的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02
Java畢業(yè)設(shè)計實戰(zhàn)之在線蛋糕銷售商城的實現(xiàn)
這是一個使用了java+JSP+Springboot+maven+mysql+ThymeLeaf+FTP開發(fā)的在線蛋糕銷售商城,是一個畢業(yè)設(shè)計的實戰(zhàn)練習(xí),具有線上蛋糕商城該有的所有功能,感興趣的朋友快來看看吧2022-01-01
Java使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫
在開發(fā)中,我們經(jīng)常會遇到這樣的需求,將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫中,這篇文章主要來和大家講講Java如何使用雙異步實現(xiàn)將Excel的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫,感興趣的可以了解下2024-01-01

