利用Freemarker动态生成PDF文档

1 依赖

  • 用到的依赖
	<dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.26-incubating</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.4.1</version>
        </dependency>

2 写freemarker工具类

  • freemarker读取模板,替换标签值。
import freemarker.cache.FileTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;

/**
 * freemarker工具类
 *
 * @Author:胡云峰
 * @Date:2023/4/14 16:38
 */
public class FreeMarkerUtil {

    /**
     * 获取模板字符串
     *
     * @param templatesPath 模板路径
     * @param templateName 模板名称
     * @param data 替换数据
     * @return
     */
    public static String getContent(String templatesPath,String templateName,Object data){
        // 获取配置
        StringWriter writer = new StringWriter();
        try {
            Template template = getConfiguration(templatesPath).getTemplate(templateName);
            template.process(data,writer);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        } finally {
            writer.flush();
            return writer.toString();
        }
    }

    /**
     * 获取配置
     * @param templateFilePath 模板路径
     * @return
     */
    private static Configuration getConfiguration(String templateFilePath){
        // 设置配置信息
        Configuration config = new Configuration(Configuration.VERSION_2_3_25);
        config.setDefaultEncoding("UTF-8");
        config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        config.setLogTemplateExceptions(false);
        // 获取模板加载器
        FileTemplateLoader fileTemplateLoader=null;
        try {
            fileTemplateLoader = new FileTemplateLoader(new File(templateFilePath));
        } catch (IOException e) {
            e.printStackTrace();
        }
        config.setTemplateLoader(fileTemplateLoader);
        return config;
    }

}

3 写生成pdf的工具类

  • 生成pdf工具
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * @Author:胡云峰
 * @Date:2023/4/15 9:01
 */
public class PdfUtil {

    /**
     * 输出内容到pdf
     *
     * @param outFilePath 输出路径
     * @param content 内容
     * @param fontPath 字体路径
     */
    public static void exportPdfFile(String outFilePath,String content,String fontPath){
        // pdf 文件
        File file = new File(outFilePath);
        // 如果文件所在的父目录不存在,则创建该目录及其所有父目录
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }

        //设置文档大小
        Document document = new Document(PageSize.A4);
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            // 创建PdfWriter实例
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);

            // 设置页眉页脚
            MyPdfEvent myPdfEvent = new MyPdfEvent();
            myPdfEvent.setFontSize(15);
            writer.setPageEvent(myPdfEvent);

            // 输出为PDF文件
            document.open();
            XMLWorkerHelper.getInstance().parseXHtml(writer,document,
                    new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)),
                    XMLWorkerHelper.class.getResourceAsStream("/default.css"),
                    StandardCharsets.UTF_8,
                    new XMLWorkerFontProvider("E:/siyuan/fonts"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            document.close();
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}

4 继承PdfPageEventHelper绑定事件

  • 设置页眉、页脚
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.IOException;

/**
 * 定义页面属性
 *
 * @Author:胡云峰
 * @Date:2023/4/15 9:48
 */
public class MyPdfEvent extends PdfPageEventHelper {

    /**
     * 字体文件名称
     */
    private String fontFileName;

    /**
     * 基础字体
     */
    private BaseFont baseFont;

    /**
     * 用于生成中文
     */
    private Font font;

    /**
     * 文档字体大小
     */
    private int fontSize;

    /**
     * 模板
     */
    private PdfTemplate templateFoot;

    /**
     * 页头模板
     */
    private PdfTemplate templateHeader;

    /**
     * 数据实体
     */
    private Object data;

    public MyPdfEvent() {
    }

    /**
     *
     * 关闭每页的时候,写入页眉,页脚等
     *
     */
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        //1.初始化字体
        initFront();
        //2.写入页眉
        writeHeader(writer,document,this.font);
        // 3.写入前半部分页脚
        try {
            writeFooter(writer,document,data,this.font);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @description 初始化字体
     */
    private void initFront(){
        try {
            if (this.baseFont == null) {
                //添加字体,以支持中文
//                String fontPath = "E:/siyuan/fonts/华康少女体W5.ttf";
                String fontPath = MyPdfEvent.class.getClassLoader().getResource("fonts/ping_fang_light.ttf").getPath();
                //创建基础字体
                this.baseFont = BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
            }
            if (this.font == null) {
                // 数据体字体
                this.font = new Font(this.baseFont, fontSize, Font.NORMAL);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param writer   PDF编写类
     * @param document PDF文档对象
     * @param font     字体设置
     * @description PDF页头设置类
     */
    private static void writeHeader(PdfWriter writer, Document document, Font font) {
        PdfContentByte cb = writer.getDirectContent();
        // 页眉横坐标居中
        float x = (document.left() + document.right()) / 2;
        // 页眉纵坐标
        float y = document.top() + 20;

        // 绘制页眉 居中
        ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, new Phrase("我是页眉", font), x, y, 0);

        // 绘制页眉下划线
        cb.setLineWidth(0.5f);
        cb.moveTo(document.left(), y-2);
        cb.lineTo(document.right(), y-2);
        cb.stroke();
    }

    /**
     * @param writer   PDF编写类
     * @param document PDF文档对象
     * @param data     业务数据
     * @param font     字体设置
     * @description PDF页脚设置类
     */
    public void writeFooter(PdfWriter writer, Document document, Object data, Font font) throws DocumentException, IOException {
//        if (data == null) {
//            return;
//        }
        int pageS = writer.getPageNumber();
        int currentPage = pageS ;
        if (currentPage <= 0) {
            return;
        }

        Phrase footer1 = new Phrase( "2023/04/15", font);
        Phrase footer2 = new Phrase(currentPage + "/", font);

        PdfContentByte cb = writer.getDirectContent();
        ColumnText.showTextAligned(
                cb,
                Element.ALIGN_LEFT,
                footer1,
                (document.left() + 10),
                document.bottom() - 20,
                0);
        ColumnText.showTextAligned(
                cb,
                Element.ALIGN_RIGHT,
                footer2,
                (document.right() - 30),
                document.bottom() - 20, 0);

        //设置模板位置
        cb.addTemplate(this.templateFoot, document.right() - 30, document.bottom() - 20);
    }

    @Override
    public void onOpenDocument(PdfWriter writer, Document document) {
        this.templateFoot = writer.getDirectContent().createTemplate(50,50);
    }

    /**
     *
     * 关闭文档时,替换模板,完成整个页眉页脚组件
     *
     */
    @Override
    public void onCloseDocument(PdfWriter writer, Document document) {
        templateFoot.beginText();
        templateFoot.setFontAndSize(this.baseFont,this.fontSize);
        int total = writer.getPageNumber() - 1;
        templateFoot.showText(total+ "");
        templateFoot.endText();
        templateFoot.closePath();
    }

    public String getFontFileName() {
        return fontFileName;
    }

    public void setFontFileName(String fontFileName) {
        this.fontFileName = fontFileName;
    }

    public BaseFont getBaseFont() {
        return baseFont;
    }

    public void setBaseFont(BaseFont baseFont) {
        this.baseFont = baseFont;
    }

    public Font getFont() {
        return font;
    }

    public void setFont(Font font) {
        this.font = font;
    }

    public int getFontSize() {
        return fontSize;
    }

    public void setFontSize(int fontSize) {
        this.fontSize = fontSize;
    }

    public PdfTemplate getTemplateFoot() {
        return templateFoot;
    }

    public void setTemplateFoot(PdfTemplate templateFoot) {
        this.templateFoot = templateFoot;
    }

    public PdfTemplate getTemplateHeader() {
        return templateHeader;
    }

    public void setTemplateHeader(PdfTemplate templateHeader) {
        this.templateHeader = templateHeader;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

5 测试

5.1 准备数据

  • 测试数据
static {
        // 设置个人信息
        person.setName("思源");
        person.setAge(1);
        person.setAvatar("C:\\Users\\Administrator\\Desktop\\siyuan.png");
        person.setSex("1");
        LocalDate localBirthDate = LocalDate.of(2022, 6, 18);
        Date birthDate = Date.from(localBirthDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
        person.setBirthDate(birthDate);
        // 添加宠物
        Pet petDog = new Pet("老大","狗");
        Pet petCat = new Pet("老二","猫");
        Pet petDog2 = new Pet("老三","狗");
        Pet petCat2 = new Pet("老四","猫");
        List<Pet> pets = Arrays.asList(petDog, petCat,petDog2,petCat2);
        person.setPetList(pets);
    }

5.2 测试

  • 发送get请求,测试,返回生成pdf路径
@GetMapping("/genePdf")
    public String generatePdf(){
        String temPath = TestController.class.getClassLoader().getResource("templates").getPath();
        String content = FreeMarkerUtil.getContent(temPath,"思源.ftl", person);
        // 定义输出文件路径
        String outFile = siYuanConfig.getOutPath() + "/" + "siyuan.pdf";
        PdfUtil.exportPdfFile(outFile,content,siYuanConfig.getFontPath());
        return outFile;
    }

5.3 测试结果

  • 生成成功
    在这里插入图片描述
  • pdf内容如下:
    在这里插入图片描述

6 ftl模版如下

  • 模版如下
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta http-equiv="Content-Style-Type" content="text/css"/>
    <title></title>
    <style type="text/css">
        body {
            font-family: pingfang sc light;
			font-size: 12px;
			line-height: 2;
        }
        .center{
            text-align: center;
            width: 100%;
        }
	
    </style>
</head>
<body>
<!--第一页开始-->
<!---页头-->
<div>
	<div>思源</div>
	<div>
		<strong>姓名:</strong>${name!'无数据'}
	</div>
	<div>
		<strong>年龄:</strong>${age!'无数据'}
	</div>
	<div><strong>性别:</strong>
		<span>
			<#if sex??>
				<#if sex=="0" >男</#if><#if sex=="1" >女</#if><#if sex=="2" >未知</#if>
			<#else>
				无数据
			</#if>
		</span>
	</div>
	<div>
		<strong>出生日期:</strong>${(birthDate?string('yyyy-MM-dd'))!'无数据'}
	</div>
	<div>
		<strong>头像:</strong><img src="${avatar}" width="170" height="170"/>
	</div>
</div>
<div>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;margin-bottom: 20px;border-style: dashed;" border="1" rules="all" >
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
	<table cellspacing="0" cellpadding="10" style="width: 100%;border-collapse: collapse;border-bottom: 1px #999999 solid;margin-bottom: 20px;text-align: center;" border="1" rules="all">
		<tbody>
			<tr>
						<td style="background: #F2F2F2;font-size: 12px;">宠物名</td>
						<td style="background: #F2F2F2;font-size: 12px;">种类</td>
			</tr>
			<#if petList??>
				<#list petList as pet>
							<tr>
								<td style="font-size: 12px;">${pet.petName!'无数据'}</td>
								<td style="font-size: 12px;">${pet.category!'无数据'}</td>
							</tr>
				</#list>
			</#if>
		</tbody>
	</table>
</div>
</body>
</html>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Spring Boot是一个用于创建独立的、基于Spring的应用程序的框架。它简化了基于Spring的应用程序的开发过程,提供了自动配置和约定大于配置的原则。LibreOffice是一个开源的办公套件软件,它提供了创建和编辑Word文档等功能。Freemarker是一个适用于Java平台的模板引擎,可以实现动态生成文本文件,比如docx文档。 在Spring Boot应用程序中使用LibreOffice和Freemarker动态生成docx文档的过程如下: 1. 在pom.xml文件中添加相关依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.libreoffice</groupId> <artifactId>libreoffice-java</artifactId> <version>1.1.0</version> </dependency> ``` 2. 创建一个Freemarker模板文件,用于定义生成docx文档的格式和内容。模板文件可以包含动态的变量,比如用户的姓名、日期等。 3. 在Spring Boot的主类中创建一个API接口,用于接收生成docx文档的请求。可以使用`@GetMapping`或`@PostMapping`注解指定API的路径。 4. 在API的方法中,使用Freemarker的模板引擎来动态生成docx文档。可以使用`Configuration`类来加载模板文件,使用`Template`类来渲染模板并生成文档内容。 5. 使用LibreOffice的Java API来将docx文档转换为其他文件格式,比如PDF。可以使用`OfficeManager`类来启动一个LibreOffice实例,使用`OfficeDocumentConverter`类来执行转换操作。 6. 将生成的docx文档保存到服务器指定的目录,并返回给客户端进行下载。 通过以上步骤,就可以在Spring Boot应用程序中利用Freemarker模板和LibreOffice实现动态生成docx文档的功能了。这样可以更加灵活和方便地生成各种格式的文档,并且可以自定义文档的内容和样式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逻辑峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值