java2word 是一个非常流行的、基于 Apache POI 封装的 Java 开源库,它的主要目标是简化 Word 文档(.docx)的生成过程,让你能用更少的代码实现复杂的 Word 排版,比如表格、图片、列表、页眉页脚等。

相比于直接使用 Apache POI,java2word 提供了更直观的 API,Table、Row、Cell、Picture 等类,让代码的可读性和维护性大大提高。
核心概念与优势
在开始之前,理解 java2word 的核心优势很重要:
- API 简洁直观:它将复杂的 POI 操作封装成了简单的 Java 对象和方法,你不需要关心 POI 底层的
XWPFDocument,XWPFTable等复杂对象。 - 面向对象:你可以像创建普通 Java 对象一样来构建 Word 文档。
new Table()就创建一个表格。 - 强大的模板支持:这是
java2word的一大亮点,你可以在 Word 模板中用${变量名}或#{表达式}的方式定义占位符,然后在 Java 代码中填充数据,非常适合生成报告、合同等格式固定的文档。 - 功能全面:支持文本、段落、表格、图片、列表、页眉页脚、水印等几乎所有常见的 Word 元素。
环境准备
你需要在你的 Java 项目中添加 java2word 的依赖,它依赖于 Apache POI,所以这两个库都需要引入。
使用 Maven
在你的 pom.xml 文件中添加以下依赖:

<dependencies>
<!-- java2word 核心库 -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.0</version> <!-- 请使用最新版本 -->
</dependency>
<!-- Apache POI 依赖,java2word 会自动引入,但显式声明更清晰 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version> <!-- 版本需与 java2word 兼容 -->
</dependency>
</dependencies>
注意:
poi-tl是java2word在 Maven 仓库中的官方 GroupId 和 ArtifactId,请务必使用最新版本,以获得更好的稳定性和功能。
使用 Gradle
在你的 build.gradle 文件中添加:
implementation 'com.deepoove:poi-tl:1.12.0' implementation 'org.apache.poi:poi-ooxml:5.2.3'
基础用法示例
下面我们通过几个经典的例子来学习如何使用 java2word。
示例 1:生成一个简单的 Word 文档
这个例子将展示如何创建文档、添加标题和普通文本。

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.Texts;
import com.deepoove.poi.data.Paragraphs;
import com.deepoove.poi.data.TextRenderData;
import java.io.FileOutputStream;
import java.io.IOException;
public class SimpleDocxExample {
public static void main(String[] args) {
// 1. 准备模板数据
// 可以是 Map<String, Object>,也可以是自定义的 Java 对象
String text = "你好,java2word!";
TextRenderData textRenderData = new TextRenderData("000000", text); // 黑色文本
// 2. 创建模板对象,这里我们直接在内存中构建,不使用模板文件
// 对于完全由代码生成的文档,可以直接使用 XWPFTemplate 的静态方法
XWPFTemplate template = XWPFTemplate.create(Paragraphs.of(textRenderData));
// 3. 输出到文件
try (FileOutputStream out = new FileOutputStream("D:/simple.docx")) {
template.writeAndClose(out);
System.out.println("文档生成成功:D:/simple.docx");
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例 2:使用模板和数据填充(最常用)
这是 java2word 最核心的功能,我们分三步走:
第 1 步:创建 Word 模板文件
在 Word 中创建一个模板,命名为 template.docx,并使用 语法定义变量。
-----------------------------------
| 员工信息表 |
-----------------------------------
| 姓名: ${name} |
| 性别: ${gender} |
| 部门: ${department} |
| 入职日期: ${entryDate} |
-----------------------------------
| 技能列表: |
| - #{each(skills)} it #{/each} |
-----------------------------------
| 个人照片: |
| ${photo} |
-----------------------------------
${name}:这是一个简单的变量占位符。#{each(skills)} it #{/each}:这是一个循环遍历占位符。it是遍历时的当前元素。${photo}:这是一个图片占位符。
第 2 步:编写 Java 代码填充数据
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.TextRenderData;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class TemplateExample {
public static void main(String[] args) {
// 1. 准备数据
Map<String, Object> data = new HashMap<>();
data.put("name", "张三");
data.put("gender", "男");
data.put("department", "研发部");
data.put("entryDate", "2025-10-27");
// 技能列表
data.put("skills", Arrays.asList("Java", "Spring Boot", "MySQL", "Vue.js"));
// 图片数据:文件路径 + 宽度 + 高度
// 图片会自动缩放以适应指定大小
String imagePath = "D:/profile.jpg"; // 确保此图片存在
data.put("photo", new PictureRenderData(100, 120, imagePath));
// 2. 加载模板文件
// 确保 template.docx 文件位于项目根目录或指定路径
XWPFTemplate template = XWPFTemplate.compile("template.docx");
// 3. 渲染数据
template.render(data);
// 4. 输出到新文件
try (FileOutputStream out = new FileOutputStream("D:/employee_report.docx")) {
template.writeAndClose(out);
System.out.println("报告生成成功:D:/employee_report.docx");
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行此代码后,你会得到一个 employee_report.docx 文件,其中所有的占位符都被成功替换。
示例 3:生成复杂表格
java2word 对表格的支持非常强大。
第 1 步:创建表格模板
在 template.docx 中创建一个表格,第一行作为表头,用 占位符。
| ID | 姓名 | 年龄 | 状态 |
|---|---|---|---|
| ${id} | ${name} | ${age} | ${status} |
第 2 步:编写 Java 代码
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TableExample {
public static void main(String[] args) {
// 1. 准备数据
Map<String, Object> data = new HashMap<>();
// 表格数据:通常是一个 List<Map> 或 List<自定义对象>
List<Map<String, Object>> tableData = new ArrayList<>();
Map<String, Object> row1 = new HashMap<>();
row1.put("id", "001");
row1.put("name", "李四");
row1.put("age", 28);
row1.put("status", "在职");
tableData.add(row1);
Map<String, Object> row2 = new HashMap<>();
row2.put("id", "002");
row2.put("name", "王五");
row2.put("age", 32);
row2.put("status", "休假");
tableData.add(row2);
data.put("users", tableData); // 将列表数据绑定到模板中的 #{each(users)} 循环
// 2. 加载并渲染模板
XWPFTemplate template = XWPFTemplate.compile("template.docx");
template.render(data);
// 3. 输出文件
try (FileOutputStream out = new FileOutputStream("D:/user_table.docx")) {
template.writeAndClose(out);
System.out.println("表格生成成功:D:/user_table.docx");
} catch (IOException e) {
e.printStackTrace();
}
}
}
模板文件需要配合循环语法使用:
假设你的模板表格只有一行,你需要这样写:
| ID | 姓名 | 年龄 | 状态 |
|---|---|---|---|
| #{each(users)} | |||
| ${it.id} | ${it.name} | ${it.age} | ${it.status} |
| #{/each} |
这里的 it 代表 users 列表中的每一个 Map 对象,通过 it.key 来访问值。
高级功能
-
页眉页脚: 通过
HeaderRenderData和FooterRenderData来设置,它们可以包含文本、图片、页码等。// 在准备数据的 Map 中添加 data.put("header", new HeaderRenderData("这是页眉")); data.put("footer", new FooterRenderData("第 #page# 页 / 共 #totalPages# 页"));模板中用
${header}和${footer}占位。 -
水印: 使用
WatermarkRenderData。// 准备水印数据(文本或图片) WatermarkRenderData watermark = new WatermarkRenderData("内部资料", "宋体", 60, Color.GRAY); // 或者使用图片水印 // WatermarkRenderData watermark = new WatermarkRenderData(new PictureRenderData(300, 150, "D:/watermark.png")); data.put("watermark", watermark);模板中用
${watermark}占位。 -
超链接: 使用
HyperlinkTextRenderData。data.put("link", new HyperlinkTextRenderData("点击访问 Google", "https://www.google.com")); -
自定义样式: 你可以通过
TextRenderData的构造函数来指定字体、颜色、大小、加粗等样式。TextRenderData title = new TextRenderData("28FF0000", "红色大标题");setBold(true);setFontFamily("微软雅黑"); data.put("title", title);
总结与最佳实践
- 模板先行:对于复杂的报告,先在 Word 中设计好模板,再用 Java 代码填充数据,这比用代码硬编码排版要高效和灵活得多。
- 数据准备:准备一个
Map<String, Object>或一个专门的 Java Bean(POJO)来存放所有需要渲染的数据,结构清晰,易于维护。 - 错误处理:文件操作(读写)可能会抛出
IOException,务必使用try-catch-finally或try-with-resources来确保资源被正确关闭。 - 查阅官方文档:
java2word(poi-tl) 的功能非常丰富,以上只是冰山一角,遇到更复杂的需求时,一定要查阅其官方文档和示例,官方 GitHub 仓库是最好的学习资源。
通过以上步骤,你就可以在 Java 项目中熟练地使用 java2word 来动态生成各种复杂的 Word 文档了。
