java使用html模板导出pdf(使用thymeleaf进行渲染)

  • 依赖
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
    
    <groupId>com.openhtmltopdfgroupId>
    <artifactId>openhtmltopdf-coreartifactId>
    <version>1.0.0version>
dependency>
<dependency>
    
    <groupId>com.openhtmltopdfgroupId>
    <artifactId>openhtmltopdf-pdfboxartifactId>
    <version>1.0.0version>
dependency>
  • 工具类
package com.shell.common.utils.pdf;

import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.springframework.util.ResourceUtils;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import java.io.OutputStream;
import java.util.Map;

public class PdfUtil {
    /**
     * @param os
     * @param pdfFileName  pdf文件名称(不包含pdf后缀)
     * @param templateName 模板名称
     * @param variables    模板变量
     */
    public static void buildPdf(OutputStream os, String pdfFileName, String templateName, Map<String, Object> variables) throws Exception {
        //构造模板引擎
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        resolver.setPrefix("templates/");//模板所在目录,相对于当前classloader的classpath。
        resolver.setSuffix(".html");//模板文件后缀
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(resolver);
        //构造上下文(Model)
        Context context = new Context();
        context.setVariable("templateName", templateName);
        context.setVariable("pdfFileName", pdfFileName);
        context.setVariables(variables);
        //渲染模板
        String example = templateEngine.process(templateName, context);
        PdfRendererBuilder builder = new PdfRendererBuilder();
        builder.useFont(ResourceUtils.getFile("classpath:templates/fonts/simsun.ttf"), "simsun");
        builder.useFastMode();
        builder.withHtmlContent(example, ResourceUtils.getURL("classpath:templates/img/").toString());
        builder.toStream(os);
        builder.run();

    }
}
  • 测试代码
package com.step.pdf.demo.controller;
import com.step.pdf.demo.util.PdfUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RestController
public class DemoController {
    @GetMapping("pdf")
    public void test(HttpServletResponse response) throws Exception {
        Map<String, Object> variables = new HashMap<>();
        variables.put("assessmentTypeName", "测试");
        variables.put("staffName", "staffName");
        variables.put("functions", "functions");
        variables.put("assessmentDate", "assessmentDate");
        variables.put("roles", "roles");
        variables.put("score", "score");
        variables.put("signature", "signature");
        PdfUtil.buildPdf(response, "用于测试的pdf", "parent", variables);
    }
}
  • 模板代码
DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8" />
    <title th:text="${pdfFileName}">title>
    <style>
        @page {
            size: A4;
            @top-center {
                content: element(header);
            }
            @bottom-center {
                font-family: 'simsun', serif;
            }
        }
        html,
        body {
            font-family: 'simsun', serif;
            font-size: 14px;
        }
        table {
            -fs-table-paginate: paginate;
            border-collapse: collapse;
            width: 100%;
        }
        .headingBox {
            font-size: 18px;
            text-align: center;
            font-style: italic;
            font-weight: bolder;
        }
        table,
        td,
        th {
            border: 0px solid #555;
            padding: 3px 5px;
        }
        .box1,
        .box2,
        .box3 {
            padding: 10px 20px;
            border-top: 1px solid #999;
        }
        .trBox {
            display: flex;
        }
        .tdBox {
            width: 50%;
            display: flex;
        }
        .titleBox {
            display: inline-block;
            width: 32%;
            font-weight: bold;
        }
        .contentBox {
            width: 68%;
            color: cornflowerblue;
        }
        .titleOverviewBox {
            display: inline-block;
            width: 64%;
            font-weight: bold;
        }
        .contentOverViewBox {
            width: 36%;
            color: cornflowerblue;
        }
        .functionTitleBox,
        .commentsTitleBox {
            font-style: italic;
            font-weight: bolder;
            margin: 0 0 0 2%;
        }
    style>
    <style>
        #app {
            border: 1px solid #999;
            width: 550px;
            box-sizing: border-box;
            margin: 0px auto;
        }
        #comm {
            height: 100px;
        }
        #content {
            white-space: pre-line;
        }
    style>
head>
<body>
<div id="app">
    <h3 th:text="'Competence Assessment_'+${assessmentTypeName}" class="headingBox">h3>
    <div class="box1">
        <table border="0px;" class="baseInfoBox">
            <tr class="trBox">
                <td class="tdBox"><span class="titleBox">Name:span><span class="contentBox" th:text="${staffName}">span>td>
                <td class="tdBox">td>
            tr>
            <tr class="trBox">
                <td class="tdBox"><span class="titleBox">Function:span><span class="contentBox" th:text="${functions}">span>td>
                <td class="tdBox"><span class="titleOverviewBox">Date:span><span class="contentOverViewBox"
                                                                                   th:text="${assessmentDate}">span>td>
            tr>
            <tr class="trBox">
                <td class="tdBox"><span class="titleBox">Role:span><span class="contentBox" th:text="${roles}">span>td>
                <td class="tdBox"><span class="titleOverviewBox">Agreegate Source:span>
                <span class="contentOverViewBox" th:text="${agreegateSource}">span>td>
            tr>
        table>
    div>
    <div th:each="item:${questionList}">
        <div class="box1">
            <h4 class="functionTitleBox" th:text="${item.functionName}+':'">h4>
            <div class="w">
                <tbody th:border="0">
                <tr>
                    <td th:text="${item.questionContent}" id="content">td>
                tr>
                tbody>
            div>
        div>
        <div class="box1">
            <h4 class="commentsTitleBox">Comments:h4>
            <div class="c" th:height="500px" id="comm">
            div>
            <div style="display: flex;">
                <div style="padding-left: 18em">
                <span th:text="'Score:          '">span><span
                        th:text="'Signature:'">span>div>
            div>
        div>
    div>
div>
body>
html>

你可能感兴趣的:(javaee,java,开发语言)