Spring Boot3 中实现按模板导出 Word 文档合同的技术指南

B站影视 内地电影 2025-09-22 19:32 1

摘要:在当今的互联网软件开发领域,开发人员经常面临着各种各样复杂的需求。其中,在业务系统中实现按照特定模板导出 Word 文档合同是一个十分常见且具有实际应用价值的需求场景。无论是大型企业的合同管理系统,还是小型创业公司的业务流程自动化,这一功能都起着关键作用。对于

在当今的互联网软件开发领域,开发人员经常面临着各种各样复杂的需求。其中,在业务系统中实现按照特定模板导出 Word 文档合同是一个十分常见且具有实际应用价值的需求场景。无论是大型企业的合同管理系统,还是小型创业公司的业务流程自动化,这一功能都起着关键作用。对于使用 Spring Boot3 进行开发的我们来说,如何高效、优雅地实现这一功能,便是本文重点探讨的内容。

在 Spring Boot3 项目中,实现按模板导出 Word 文档合同,目前比较常用且高效的技术方案主要有两种,分别是使用 POI-TL 和 Freemarker。下面我们详细了解一下使用 POI-TL方案的特点。

POI-TL(POI Template Language)是一款基于 Apache POI 的 Word 模板引擎,它以其简洁易用的特性,在开发者群体中备受青睐。POI-TL 的核心优势在于,通过简单直观的{{}}语法占位符,就能够在 Word 模板中精准插入动态数据,实现极为高效的文档填充。它的功能丰富多样,全面支持文本、表格、图片、循环列表等复杂数据结构的填充,并且对 docx 格式有着良好的兼容性,这使得它在办公文档生成场景中如鱼得水。

要在 Spring Boot3 项目中使用 POI-TL,我们首先需要在项目的pom.xml文件中添加相关依赖,代码如下:

com.deepoove poi-tl 1.10.0

添加好依赖后,接下来就是准备我们的 Word 模板。我们可以使用 Microsoft Office、WPS Office 等常用办公软件创建一个.docx格式的 Word 模板文件。在模板中,按照 POI-TL 的语法规则,使用{{变量名}}来标记需要动态填充数据的位置。例如,如果我们要在合同模板中填充合同编号、甲方名称、乙方名称等信息,在模板中可以这样设置:

合同编号:{{contractNumber}}甲方:{{partyA}}乙方:{{partyB}}

假设我们还需要动态生成一个合同条款列表,POI-TL 也能轻松应对。在模板中可以这样设计表格结构:

{{#clauseTable}}| 条款序号 | 条款内容 || {{clauseIndex}} | {{clauseContent}} |{{/clauseTable}}

这里的{{#clauseTable}}和{{/clauseTable}}表示这是一个循环结构,clauseTable是循环的标识,在代码实现中,我们会提供一个包含条款序号和条款内容的集合数据,POI-TL 会根据集合的大小,自动循环填充表格行。

接下来,我们以 POI-TL 方案为例,详细讲解在 Spring Boot3 中实现按模板导出 Word 文档合同的具体步骤。

在 java 代码中,我们首先需要创建一个数据模型类,用于封装要填充到 Word 模板中的数据。假设我们的合同包含合同编号、甲方信息、乙方信息、合同条款列表等内容,数据模型类可以这样定义:

import java.util.List;public class ContractData { private String contractNumber; private String partyA; private String partyB; private List clauseList; // 省略getter和setter方法 public static class Clause { private int clauseIndex; private String clauseContent; // 省略getter和setter方法 }}

在实际应用中,我们可以从数据库查询数据,或者通过其他业务逻辑获取数据,然后将数据填充到这个数据模型类的实例中。

下面是使用 POI-TL 生成 Word 文档的核心代码:

import com.deepoove.poi.XWPFTemplate;import java.io.FileOutputStream;import java.io.IOException;import java.util.HashMap;import java.util.Map;public class WordContractGenerator { public static void generatecontract(ContractData contractData, String templatePath, String outputPath) throws IOException { // 读取模板文件 XWPFTemplate template = XWPFTemplate.compile(templatePath); // 创建用于填充模板的数据Map Map dataMap = new HashMap; dataMap.put("contractNumber", contractData.getContractNumber); dataMap.put("partyA", contractData.getPartyA); dataMap.put("partyB", contractData.getPartyB); dataMap.put("clauseTable", contractData.getClauseList); // 进行模板填充 template.render(dataMap); // 生成新的Word文件 try (FileOutputStream out = new FileOutputStream(outputPath)) { template.write(out); } // 关闭资源 template.close; }}

在这段代码中,generateContract方法接收合同数据对象、模板文件路径和输出文件路径作为参数。首先通过XWPFTemplate.compile方法读取模板文件,然后将数据模型中的数据放入dataMap中,注意这里的键名要与 Word 模板中的占位符变量名一致。接着调用template.render方法进行模板填充,最后通过template.write方法将填充好数据的模板写入到指定的输出文件路径中,并关闭相关资源。

如果我们希望在 Web 项目中,用户能够通过浏览器下载生成的 Word 合同文档,我们可以在 Spring Boot 的控制器中编写如下代码:

import com.deepoove.poi.XWPFTemplate;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;import java.io.OutputStream;import java.util.HashMap;import java.util.Map;@RestController@RequestMapping("/contract")public class ContractController { @GetMapping("/download") public void downloadContract(HttpServletResponse response) throws Exception { // 模拟获取合同数据 ContractData contractData = new ContractData; contractData.setContractNumber("20250922001"); contractData.setPartyA("甲方公司名称"); contractData.setPartyB("乙方公司名称"); // 模拟合同条款数据 ContractData.Clause clause1 = new ContractData.Clause; clause1.setClauseIndex(1); clause1.setClauseContent("第一条:双方权利义务..."); ContractData.Clause clause2 = new ContractData.Clause; clause2.setClauseIndex(2); clause2.setClauseContent("第二条:违约责任..."); contractData.getClauseList.add(clause1); contractData.getClauseList.add(clause2); // 设置响应头,指定文件名 response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); response.setHeader("Content-Disposition", "attachment; filename=contract.docx"); // 加载模板 XWPFTemplate template = XWPFTemplate.compile("template/contractTemplate.docx"); // 创建用于填充模板的数据Map Map dataMap = new HashMap; dataMap.put("contractNumber", contractData.getContractNumber); dataMap.put("partyA", contractData.getPartyA); dataMap.put("partyB", contractData.getPartyB); dataMap.put("clauseTable", contractData.getClauseList); // 渲染模板 template.render(dataMap); // 输出到客户端 OutputStream out = response.getOutputStream; template.write(out); out.flush; out.close; template.close; }}

在这段代码中,@GetMapping("/download")注解的方法用于处理用户的下载请求。首先模拟获取合同数据,然后设置响应头,指定下载文件的类型和文件名。接着加载 Word 模板文件,创建数据 Map 并填充数据,最后通过template.render渲染模板,将生成的 Word 文档通过OutputStream输出到客户端浏览器,完成下载功能。

相较于 Freemarker 的 “XML 间接适配”,POI-TL(Poi Template Language)是专为 Word 设计的模板引擎,基于 Apache POI 封装,核心优势在于:

模板制作零门槛:直接在 Word 中用 {{变量名}} 标记占位符,无需修改 XML 或改后缀,开发人员和产品经理可协作制作模板;

支持复杂数据填充:原生支持循环列表(如合同中的 “服务清单”)、图片(如公司公章)、条件判断(如 “是否需要担保条款”);

Spring Boot3 兼容性好:最新版本 1.10.0 已适配 Java 17(Spring Boot3 默认依赖),无版本冲突问题;

性能更优:避免 XML 解析的中间步骤,生成 100 页合同的速度比 Freemarker 快 30% 左右(实测数据)。

来源:从程序员到架构师一点号

相关推荐