FreeMarker


十二月的第六周,来学习 FreeMarker。

在我敲出上句话时,我甚至都不知道 FreeMarker 是什么……工作需要,硬头皮写。


FreeMarker 是一种模板引擎,通过 Java 语言使用。官方是这么解释“模板引擎”的:

(模板引擎是)一种基于模板和要改变的数据,用来生成输出文本的通用工具。

又是一个不说人话的解释。

我理解的模板引擎,就是让程序自动使用模板生成结果的工具,比如:

1
2
3
4
5
请假条:昨日偶感风寒,身体抱疾,兹请假一天。请假人:${name}

请假条:昨日偶感风寒,身体抱疾,兹请假一天。请假人:张三
请假条:昨日偶感风寒,身体抱疾,兹请假一天。请假人:李四
请假条:昨日偶感风寒,身体抱疾,兹请假一天。请假人:王二麻子

FreeMarker 能够读取模板中的占位符 ${...},并根据外部输入的值,自动替换掉占位符,生成最终的结果。

如此一个替换文本的工具,广泛使用在 web 前端、配置文件、源代码中。它是一种老派的 old school 工具,现在前端都没什么人用了。


一会再学习 FreeMarker 的语法,暂且认为 FreeMarker 就是在替换字符串,把 ${...} 换成具体的值。

最为基础的使用 FreeMarker 的方式,就是 IO 输入模板文件,然后 FreeMarker 咣咣工作,最终 IO 输出生成文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 由于处理IO异常太过繁琐,模糊了主干内容,这里忽略处理异常的部分

// IO输入模板文件
Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
configuration.setDirectoryForTemplateLoading(new File("C:\\Users\\thinkpad\\Desktop"));
Template template = configuration.getTemplate("template.ftl");

// 设置替换值
Map<String, Object> map = new HashMap<>(8);
map.put("name", "张三");
map.put("age", 18);

// IO输出结果文件
File out = new File("C:\\Users\\thinkpad\\Desktop\\" + "result.txt");
Writer outWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(out)));
template.process(map, outWriter);
输入(template.ftl) 输出(result.txt)
人员信息
姓名:${name}
年龄:${age}
人员信息
姓名:张三
年龄:18

上面的代码是在做这样一件事:

  1. 实例化一个 FreeMarker 对象出来(configuration)
  2. 配置 FreeMarker 的参数,其中包括输入地址(模板)、输出地址(结果)、FreeMarker 的版本。
  3. 给定想替换成的值,让 FreeMarker 去工作(替换)。

顺便提一嘴,模板文件 template.ftl 的后缀名是 ftl,全称是 FreeMarker Template Language,是 FreeMarker 的标准模板文件格式。

上面这种方式,是显式地配置 FreeMarker,手动给定输出输出的文件地址,设定好 FreeMarker 的版本号,然后去使用。除了这种方式之外,还可以以配置文件的方式,在外部去设定好 FreeMarker 的各项参数,然后直接使用。比如在 Spring 框架下,都是外部设定好 FreeMarker 的参数,然后注入到要使用的地方。

但是我看了看,有点复杂……算了,看看语法就行了,佛了。


来看 FreeMarker 的语法。

首先推荐官方文档,尽管官方的介绍有一些翻译腔,但是在语法介绍部分,是极尽所能地把用户当小白来教学。

FreeMarker官方文档

(你看看这个恳切程度!)

粗略地学习之后发现,FreeMarker 不仅仅是一个替换字符串的工具,而像是一个完整的语言体系,除了基本的替换,还有许多内置函数和逻辑控制,实际上要学习的内容是非常多的。

本周又是摸鱼的一周,仅将常用的替换语法写在下面。

1
2
3
4
5
6
7
8
9
10
11
12
// ...

// 配置准备替换的值
Map<String, Object> map = new HashMap<>(8);
map.put("name", "张三");
Map person = new HashMap();
person.put("age", 17);
map.put("person", person);
List hobby = Arrays.asList("唱", "跳", "RAP", "篮球");
map.put("hobby", hobby);

// ...
模板文件 输出文件
人员信息

姓名:${name}

年龄:${person.age}

<#if (person.age >= 18)>
成年
<#else>
未成年
</#if>

爱好:<#list hobby as h>${h} </#list>

当前时间:${.now?string[“yyyy-MM-dd HH:mm:ss”]}
人员信息

姓名:张三

年龄:17

未成年

爱好:唱 跳 RAP 篮球

当前时间:2019-12-29 09:40:58