FreeMarker 是一款基于 Java 的模板引擎,主要用于生成文本输出,比如 HTML 网页、电子邮件、配置文件、源代码等。它是一个开源项目,由 Apache 软件基金会维护,以其简洁性、灵活性和高性能在 Java 开发领域广泛应用。
主要特点
- 语法简单:FreeMarker 采用了简单易懂的模板语法,主要由插值(如
${variable}
)、指令(如#if
、#list
)和注释(如<#-- 这是注释 -->
)构成,开发人员能快速上手。 - 数据模型无关:它不依赖特定的数据模型,能够与任何 Java 对象或数据结构配合使用,如 JavaBean、Map、List 等。只需将数据传递给模板,就可以在模板中使用这些数据进行动态内容生成。
- 强大的模板继承和包含机制:支持模板继承和包含,方便对模板进行模块化设计和复用。可以创建基础模板,然后让其他模板继承或包含它,减少代码重复。
- 高性能:FreeMarker 的模板解析和渲染速度快,能够高效地处理大量数据和复杂模板。它在编译模板时进行了优化,减少了运行时的开销。
- 安全可靠:在模板中执行的代码是安全的,不会对系统造成潜在的安全风险。它不允许在模板中执行任意 Java 代码,避免了代码注入等安全问题。
话不多说,直接进入正题,想必都知道这个是用来干嘛的,无非就是把需要的数据插入已经准备好的word文档里面动态生成
一、准备word模板
1、创建一个word文档,里面随便填写一点数据
2、另存为xml文档
并且放入项目下的resources文件夹下面
3、用idea或者其他开发工具打开,并且代码格式化一下,找到你刚才所填写的数据,用占位符代替你所需要替换的数据,${name}
我这里使用了表格,因为表格里面的数据是会存在有多条数据的情况,所以使用了#list 进行循环遍历
4、编写代码
(1)、生成word文档工具类
/**
* 生成 word 文件
*
* @param dataMap 待填充数据
* @param templateName 模板文件名称
* @param filePath 模板文件路径
* @param fileName 生成的 word 文件名称
* @param response 响应流
*/
public static void createWord(Map dataMap, String templateName, String filePath, String fileName
, HttpServletResponse response){
// 创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
// 设置编码
configuration.setDefaultEncoding(StandardCharsets.UTF_8.name());
// ftl模板文件
configuration.setClassForTemplateLoading(WordUtil.class, filePath);
try {
// 获取模板
Template template = configuration.getTemplate(templateName);
// 获取当前时间
String time = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
fileName = time+ fileName;
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setCharacterEncoding("utf-8");
fileName = URLEncoder.encode(fileName, "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
// 获取响应输出流
OutputStream outputStream = response.getOutputStream();
// 转成所需要的流
OutputStreamWriter streamWriter = new OutputStreamWriter(outputStream);
Writer out = new BufferedWriter(streamWriter);
template.process(dataMap, out);
// 关闭流
outputStream.close();
streamWriter.close();
} catch (Exception e){
e.printStackTrace();
}
}
(2)、准备请求接口和数据
我这边就直接把业务逻辑和接口放在一起了,就不进行拆分了
/**
* 生成 word 文件
*/
@GetMapping("/createWord")
public void createWord(HttpServletResponse response){
Map<String, Object> dataMap = new HashMap<>();
dataMap.put("year", "2025");
// 创建表格数据
List<Map<String, String>> list = new ArrayList<>();
for (int i = 1; i <= 12; i++) {
Map<String, String> data = new HashMap<>();
data.put("month", i + "月");
data.put("price", "3000");
list.add(data);
}
dataMap.put("data", list);
// 模板文件名称
String templateName = "测试.xml";
// 模板文件路径(项目resources目录下的文件夹)
String filePath = "/files";
// 生成的 word 文件名称
String fileName = "test.docx";
// 生成 word 文件
createWord(dataMap, templateName, filePath, fileName, response);
}
5、到这里就结束了,直接请求这个接口就可以生成文档了