自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

完美!SpringBoot3.3 + OpenPDF + HTML模板高效生成PDF文檔

開(kāi)發(fā) 前端
通過(guò)本文的講解,我們成功實(shí)現(xiàn)了使用 SpringBoot 3.3 結(jié)合 Thymeleaf 模板引擎、高效生成PDF文檔的功能。從環(huán)境配置、依賴管理到代碼實(shí)現(xiàn),再到樣式設(shè)計(jì)和復(fù)雜布局處理,都進(jìn)行了詳細(xì)的闡述。

在現(xiàn)代Web開(kāi)發(fā)中,生成PDF文檔是一個(gè)常見(jiàn)的需求,無(wú)論是生成報(bào)表、導(dǎo)出合同還是制作發(fā)票,都需要高效、靈活的PDF生成方案。本篇文章將深入探討如何使用 SpringBoot 3.3 結(jié)合 Thymeleaf、JavaScript 和 Bootstrap 實(shí)現(xiàn)高效的PDF文檔生成,并通過(guò)詳細(xì)的代碼示例和配置說(shuō)明,幫助大家快速上手這一技術(shù)方案。

隨著業(yè)務(wù)需求的不斷增長(zhǎng),傳統(tǒng)的PDF生成方式已經(jīng)難以滿足復(fù)雜、多樣化的需求。使用HTML模板生成PDF具有以下優(yōu)勢(shì):

  • 可視化強(qiáng):可以直接在瀏覽器中預(yù)覽效果,所見(jiàn)即所得。
  • 樣式靈活:借助CSS和Bootstrap,可以輕松實(shí)現(xiàn)復(fù)雜的布局和樣式。
  • 開(kāi)發(fā)高效:前后端分離,開(kāi)發(fā)維護(hù)更加便捷。

本篇文章將基于 SpringBoot 3.3,利用 Thymeleaf 模板引擎和 OpenPDF 庫(kù),將HTML模板渲染為PDF文檔,實(shí)現(xiàn)高效、靈活的PDF生成方案。

運(yùn)行效果:

圖片圖片

生成 pdf 效果:

圖片圖片

若想獲取項(xiàng)目完整代碼以及其他文章的項(xiàng)目源碼,且在代碼編寫時(shí)遇到問(wèn)題需要咨詢交流,歡迎加入下方的知識(shí)星球。

項(xiàng)目環(huán)境準(zhǔn)備

1. 開(kāi)發(fā)環(huán)境

  • JDK 17:確保您的項(xiàng)目運(yùn)行在Java 17環(huán)境下。
  • Maven 3.8+:用于項(xiàng)目構(gòu)建和依賴管理。
  • SpringBoot 3.3:最新版本的SpringBoot框架。
  • Thymeleaf:流行的Java模板引擎。
  • OpenPDF:開(kāi)源的PDF生成庫(kù)。
  • Bootstrap 5:用于前端頁(yè)面的布局和樣式。
  • JavaScript:用于增強(qiáng)頁(yè)面交互性。

2. 項(xiàng)目結(jié)構(gòu)

項(xiàng)目的基本結(jié)構(gòu)如下:

pdf-demo
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.icoderoad.pdfdemo
│   │   │       ├── controller
│   │   │       ├── service
│   │   │       └── PdfDemoApplication.java
│   │   ├── resources
│   │   │   ├── templates
│   │   │   ├── fonts/SimSun.ttf
│   │   │   ├── static
│   │   │   └── application.yml
├── pom.xml

項(xiàng)目依賴配置(pom.xml)

首先,我們需要在 pom.xml 中添加必要的依賴。

<?xml versinotallow="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.3.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.icoderoad</groupId>
	<artifactId>pdfdemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>pdfdemo</name>
	<description>Demo project for Spring Boot</description>
	
	<properties>
		<java.version>17</java.version>
		<openpdf.version>1.3.29</openpdf.version>
	</properties>
	<dependencies>
		<!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Thymeleaf 模板引擎 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- OpenPDF 庫(kù) -->
        <dependency>
            <groupId>com.github.librepdf</groupId>
            <artifactId>openpdf</artifactId>
            <version>${openpdf.version}</version>
        </dependency>

        <!-- HTML轉(zhuǎn)PDF工具(flying-saucer) -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-core</artifactId>
            <version>9.1.20</version>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-openpdf</artifactId>
            <version>9.1.20</version>
        </dependency>

        <!-- 日志框架 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

</project>

依賴說(shuō)明:

  • spring-boot-starter-web:提供Web開(kāi)發(fā)所需的基本依賴。
  • spring-boot-starter-thymeleaf:集成Thymeleaf模板引擎。
  • openpdf:用于生成PDF文檔的核心庫(kù)。
  • flying-saucer:將HTML轉(zhuǎn)換為PDF的工具,結(jié)合OpenPDF使用。
  • spring-boot-starter-logging:提供日志支持。

應(yīng)用配置(application.yml)

在 src/main/resources 目錄下創(chuàng)建 application.yml 配置文件。

# application.yml
server:
  port: 8080

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mode: HTML
    encoding: UTF-8
    cache: false

配置說(shuō)明:

  • server.port:設(shè)置應(yīng)用運(yùn)行端口為8080。
  • spring.thymeleaf:配置Thymeleaf模板引擎的相關(guān)屬性,指定模板路徑、后綴、編碼等。

后端代碼實(shí)現(xiàn)

1. 主啟動(dòng)類

創(chuàng)建主啟動(dòng)類 PdfDemoApplication.java。

package com.icoderoad.pdfdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PdfdemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(PdfdemoApplication.class, args);
	}

}

2. 控制器層

創(chuàng)建控制器類 PdfController.java,負(fù)責(zé)處理請(qǐng)求和生成PDF文檔。

// PdfController.java
package com.icoderoad.pdfdemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import com.icoderoad.pdfdemo.service.PdfService;

import jakarta.servlet.http.HttpServletResponse;

@Controller
public class PdfController {

    @Autowired
    private PdfService pdfService;

    /**
     * 顯示數(shù)據(jù)預(yù)覽頁(yè)面
     * @param model 模型數(shù)據(jù)
     * @return 模板名稱
     */
    @GetMapping("/preview")
    public String preview(Model model) {
        model.addAttribute("title", "PDF文檔預(yù)覽");
        model.addAttribute("content", "這是一個(gè)使用Thymeleaf渲染的HTML內(nèi)容,將被轉(zhuǎn)換為PDF文檔。");
        return "preview";
    }

    /**
     * 生成PDF文檔并下載
     * @param response HTTP響應(yīng)
     * @throws Exception 異常
     */
    @GetMapping("/download")
    public void downloadPdf(HttpServletResponse response) throws Exception {
        String htmlContent = pdfService.generateHtmlContent();
        pdfService.generatePdf(response, htmlContent);
    }
}

代碼說(shuō)明:

  • /preview:用于展示HTML內(nèi)容的預(yù)覽頁(yè)面,方便在生成PDF前查看效果。
  • /download:生成PDF文檔并通過(guò)HTTP響應(yīng)下載。

3. 服務(wù)層

創(chuàng)建服務(wù)類 PdfService.java,負(fù)責(zé)處理HTML內(nèi)容的生成和PDF文檔的生成。

package com.icoderoad.pdfdemo.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.lowagie.text.DocumentException;

import jakarta.servlet.http.HttpServletResponse;

@Service
public class PdfService {

    @Autowired
    private TemplateEngine templateEngine;

    /**
     * 生成HTML內(nèi)容
     * @return 渲染后的HTML字符串
     */
    public String generateHtmlContent() {
        Context context = new Context();
        context.setVariable("title", "PDF文檔標(biāo)題");
        context.setVariable("content", 
        		"這是PDF文檔的主要內(nèi)容:"
        		+ "“成功并不是終點(diǎn),失敗也不是終結(jié),最重要的是繼續(xù)前行的勇氣。在人生的旅途中,我們會(huì)遇到許多挑戰(zhàn)與挫折,這些都是成長(zhǎng)的必經(jīng)之路。每一次跌倒都是一次學(xué)習(xí)的機(jī)會(huì),每一次失敗都為成功鋪設(shè)了基礎(chǔ)。只要我們保持信念,不斷努力,最終會(huì)到達(dá)夢(mèng)想的彼岸。無(wú)論前方的路有多么坎坷,只要心懷希望,我們就有無(wú)限的可能性去改變自己的命運(yùn),實(shí)現(xiàn)心中的理想。”"
        		+ "由Thymeleaf模板引擎渲染。"
        		+ "");
        return templateEngine.process("pdf_template", context);
    }

    /**
     * 將HTML內(nèi)容轉(zhuǎn)換為PDF并寫入響應(yīng)
     * @param response HTTP響應(yīng)
     * @param htmlContent HTML內(nèi)容
     * @throws IOException IO異常
     * @throws DocumentException 文檔異常
     */
    public void generatePdf(HttpServletResponse response, String htmlContent) throws IOException, DocumentException {
        // 設(shè)置響應(yīng)類型
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=generated.pdf");

        // 創(chuàng)建ITextRenderer實(shí)例
        ITextRenderer renderer = new ITextRenderer();
       
        // 設(shè)置字體路徑,使用 classpath 加載字體
        ITextFontResolver fontResolver = renderer.getFontResolver();
        ClassPathResource fontResource = new ClassPathResource("fonts/SimSun.ttf");
        System.out.println(fontResource.getFile().getAbsolutePath());
        fontResolver.addFont(fontResource.getFile().getAbsolutePath(), "Identity-H", true);
        
        renderer.setDocumentFromString(htmlContent);
        renderer.layout();

        // 輸出PDF到響應(yīng)輸出流
        try (OutputStream outputStream = response.getOutputStream()) {
            renderer.createPDF(outputStream);
            outputStream.flush();
        }
    }
}

代碼說(shuō)明:

  • generateHtmlContent():使用Thymeleaf模板引擎渲染HTML內(nèi)容,填充模板變量。
  • generatePdf():使用 ITextRenderer 將HTML內(nèi)容轉(zhuǎn)換為PDF文檔,并寫入HTTP響應(yīng),供用戶下載。

注意事項(xiàng):

  • 模板引擎配置:TemplateEngine 需要在配置類中進(jìn)行相應(yīng)設(shè)置,這里通過(guò)自動(dòng)裝配注入。
  • 字符編碼:確保HTML內(nèi)容的字符編碼為UTF-8,避免中文亂碼。

前端代碼實(shí)現(xiàn)

1. Thymeleaf模板

在 src/main/resources/templates 目錄下創(chuàng)建 preview.html 和 pdf_template.html 兩個(gè)模板文件。

1.1 preview.html

用于在瀏覽器中預(yù)覽內(nèi)容。

<!-- preview.html -->
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title th:text="${title}">PDF預(yù)覽</title>
    <!-- 引入Bootstrap CSS -->
    <link rel="stylesheet" >
</head>
<body>
    <div class="container mt-5">
        <h1 class="text-center" th:text="${title}">PDF文檔預(yù)覽</h1>
        <p class="mt-4" th:text="${content}">這里是內(nèi)容部分。</p>
        <div class="text-center mt-5">
            <a href="/pdf-demo/download" class="btn btn-primary">下載PDF文檔</a>
        </div>
    </div>
    <!-- 引入Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

代碼說(shuō)明:

  • 使用 Bootstrap 5 進(jìn)行簡(jiǎn)單的頁(yè)面布局和樣式設(shè)計(jì)。
  • 通過(guò)Thymeleaf的 th:text 屬性渲染動(dòng)態(tài)內(nèi)容。
  • 提供一個(gè)下載PDF的按鈕,鏈接到 /download`。

1.2 pdf_template.html

用于生成PDF的模板。

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title th:text="${title}">PDF文檔</title>
    <style>
        /* 內(nèi)聯(lián)CSS樣式,確保在PDF中正確渲染 */
        body {
            font-family: "SimSun", serif;
            padding: 20px;
            line-height: 1.6;
        }
        h1 {
            text-align: center;
            margin-bottom: 40px;
            color: #333;
        }
        p {
            font-size: 16px;
            color: #555;
        }
        .footer {
            text-align: center;
            margin-top: 50px;
            font-size: 12px;
            color: #999;
        }
    </style>
</head>
<body>
    <h1 th:text="${title}">PDF文檔標(biāo)題</h1>
    <p th:text="${content}">這是PDF文檔的內(nèi)容部分,由Thymeleaf模板引擎渲染。</p>
    <div class="footer">
        <p>? 2024 路條編程 - 保留所有權(quán)利。</p>
    </div>
</body>
</html>

代碼說(shuō)明:

  • 內(nèi)聯(lián)樣式:為了確保PDF中樣式正確渲染,使用內(nèi)聯(lián)CSS樣式。
  • 字體設(shè)置:指定 font-family 為中文字體(如 "SimSun"),避免中文顯示亂碼。
  • 內(nèi)容布局:簡(jiǎn)單的標(biāo)題、內(nèi)容和頁(yè)腳布局,滿足基本的PDF文檔需求。

2. 靜態(tài)資源

對(duì)于簡(jiǎn)單的示例,我們直接使用CDN引入Bootstrap的CSS和JS。如果需要自定義樣式和腳本,可以在 src/main/resources/static 目錄下添加相應(yīng)的文件。

運(yùn)行與測(cè)試

1. 啟動(dòng)應(yīng)用

在項(xiàng)目根目錄下執(zhí)行以下命令啟動(dòng)應(yīng)用:

mvn spring-boot:run

2. 訪問(wèn)預(yù)覽頁(yè)面

在瀏覽器中訪問(wèn):

http://localhost:8080/preview

您將看到預(yù)覽頁(yè)面,展示了將要生成的PDF內(nèi)容。

3. 下載PDF文檔

在預(yù)覽頁(yè)面點(diǎn)擊“下載PDF文檔”按鈕,瀏覽器將自動(dòng)下載生成的PDF文件 generated.pdf。

效果展示:

生成的PDF文檔應(yīng)當(dāng)包含正確的中文內(nèi)容和樣式,確保沒(méi)有亂碼和樣式錯(cuò)亂。

深度解析

1. 為什么選擇OpenPDF和Flying Saucer

OpenPDF 是一個(gè)功能強(qiáng)大且穩(wěn)定的開(kāi)源PDF庫(kù),支持豐富的PDF操作。而 Flying Saucer 是一個(gè)專門用于將XHTML/CSS轉(zhuǎn)換為PDF的庫(kù),與OpenPDF兼容性良好。兩者結(jié)合,可以方便地將HTML模板轉(zhuǎn)換為高質(zhì)量的PDF文檔。

優(yōu)勢(shì):

  • 易于使用:API簡(jiǎn)潔明了,集成方便。
  • 支持CSS樣式:能夠很好地渲染復(fù)雜的CSS樣式,滿足多樣化的布局需求。
  • 開(kāi)源免費(fèi):無(wú)版權(quán)限制,適用于商業(yè)項(xiàng)目。

2. 字體和編碼問(wèn)題

在生成包含中文內(nèi)容的PDF時(shí),常常會(huì)遇到亂碼或字體缺失的問(wèn)題。為了解決這些問(wèn)題,我們需要:

  • 指定中文字體:在CSS中設(shè)置 font-family 為系統(tǒng)支持的中文字體,如 "SimSun"、"Microsoft YaHei" 等。
  • 嵌入字體:確保PDF中嵌入所需的字體文件,可以通過(guò)配置ITextRenderer來(lái)實(shí)現(xiàn)。
  • 設(shè)置編碼:確保HTML內(nèi)容和生成的PDF使用統(tǒng)一的UTF-8編碼。

示例:嵌入字體

renderer.getFontResolver().addFont("path/to/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

注意:需要將字體文件放在項(xiàng)目的資源目錄中,并指定正確的路徑。

3. 處理復(fù)雜布局和樣式

對(duì)于復(fù)雜的PDF文檔,可以在HTML模板中使用更豐富的Bootstrap組件和自定義CSS,實(shí)現(xiàn)多欄布局、表格、圖片等元素。同時(shí),Thymeleaf的強(qiáng)大模板功能也可以幫助我們動(dòng)態(tài)生成復(fù)雜的內(nèi)容。

示例:在模板中使用表格

<table class="table table-bordered">
    <thead>
        <tr>
            <th>序號(hào)</th>
            <th>名稱</th>
            <th>描述</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>示例項(xiàng)</td>
            <td>這是一個(gè)示例描述。</td>
        </tr>
        <!-- 更多行 -->
    </tbody>
</table>

4. 動(dòng)態(tài)數(shù)據(jù)填充

通過(guò)在服務(wù)層獲取數(shù)據(jù)庫(kù)或其他數(shù)據(jù)源的數(shù)據(jù),并將其傳遞給Thymeleaf模板,我們可以動(dòng)態(tài)生成包含業(yè)務(wù)數(shù)據(jù)的PDF文檔。

示例:傳遞數(shù)據(jù)列表

List<Item> items = itemService.getItems();
context.setVariable("items", items);

在模板中迭代顯示數(shù)據(jù):

<tbody>
    <tr th:each="item, iterStat : ${items}">
        <td th:text="${iterStat.index + 1}">1</td>
        <td th:text="${item.name}">示例項(xiàng)</td>
        <td th:text="${item.description}">這是一個(gè)示例描述。</td>
    </tr>
</tbody>

總結(jié)

通過(guò)本文的講解,我們成功實(shí)現(xiàn)了使用 SpringBoot 3.3 結(jié)合 Thymeleaf 模板引擎、高效生成PDF文檔的功能。從環(huán)境配置、依賴管理到代碼實(shí)現(xiàn),再到樣式設(shè)計(jì)和復(fù)雜布局處理,都進(jìn)行了詳細(xì)的闡述。

優(yōu)勢(shì)總結(jié):

  • 高效性:利用現(xiàn)有的HTML模板和樣式,快速生成所見(jiàn)即所得的PDF文檔。
  • 靈活性:通過(guò)模板和數(shù)據(jù)的結(jié)合,輕松實(shí)現(xiàn)動(dòng)態(tài)內(nèi)容的生成。
  • 可維護(hù)性:清晰的前后端分離,方便維護(hù)和擴(kuò)展。

未來(lái)展望:

  • 多語(yǔ)言支持:通過(guò)國(guó)際化配置,實(shí)現(xiàn)PDF文檔的多語(yǔ)言版本。
  • 更復(fù)雜的樣式:引入更豐富的前端框架,如Tailwind CSS,提升文檔的美觀度。
  • 性能優(yōu)化:對(duì)于大批量PDF生成的場(chǎng)景,可以考慮異步處理和緩存機(jī)制,提升性能。

希望本文能對(duì)大家的開(kāi)發(fā)工作有所幫助,助大家在項(xiàng)目中高效地實(shí)現(xiàn)PDF文檔生成功能。

責(zé)任編輯:武曉燕 來(lái)源: 路條編程
相關(guān)推薦

2024-07-29 08:30:24

2024-09-04 11:16:44

端口Spring配置類

2024-09-02 08:17:18

2024-09-30 08:10:22

2024-09-03 10:44:32

2024-09-06 10:05:47

SpELSpring權(quán)限

2023-02-26 10:16:19

JavaPDF文檔

2024-09-03 08:26:59

Spring格式模板

2022-11-23 07:30:11

2024-09-09 11:35:35

2024-10-15 10:38:32

2023-12-12 13:42:00

微服務(wù)生態(tài)系統(tǒng)Spring

2024-10-16 12:23:55

技巧Spring驗(yàn)證

2024-09-05 09:35:58

CGLIBSpring動(dòng)態(tài)代理

2024-10-30 08:05:01

Spring參數(shù)電子簽章

2024-08-13 10:36:25

SpringScrew數(shù)據(jù)庫(kù)

2024-09-29 10:39:48

RSocketWebSocket通信

2024-09-13 10:21:50

2023-12-29 09:04:01

前端文件處理庫(kù)PDF.js

2024-10-07 08:18:05

SpringBOM管理
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)