freemarker
概述
FreeMarker
是一款模板引擎,即能够基于模板和要改变的数据,来生成输出文本(比如html网页、电子邮件、配置文件、源代码等)的通用工具。

入门案例
springboot
整合freemarker
,生成的静态文件作为mvc
视图返回
导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.3.9.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> <version>2.3.9.RELEASE</version> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.3.9.RELEAS</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.1</version> </dependency>
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-io</artifactId> <version>1.3.2</version> </dependency> </dependencies>
|
设置配置文件
application.yml
1 2 3 4 5 6 7 8 9 10
| spring: application: name: freeMarker-demo freemarker: cache: false settings: template_update_delay: 0 suffix: .ftl server: port: 9000
|
创建模板文件
在resources
下创建templates
,此目录为freemarker
的默认模板存放目录
在templates
文件夹下创建模板文件f1.ftl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello World!</title> </head> <body> <b>普通文本 String 展示:</b><br><br> Hello ${name} <br> <hr> <b>对象Student中的数据展示:</b><br/> 姓名:${stu.name}<br/> 年龄:${stu.age} <hr> </body> </html>
|
创建模板类
1 2 3 4 5 6 7
| @Data public class Student { private String name; private int age; private Date birthday; private Float money; }
|
编写controller层代码
将freeMarker
生成的静态文件作为视图返回
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Controller public class FreeMarkerController {
@GetMapping("/fHello") public String fHello(Model model){ model.addAttribute("name","李白"); Student stu = new Student(); stu.setName("张飞"); stu.setAge(28); model.addAttribute("stu",stu); return "f1"; } }
|
访问页面
访问http://localhost:9000/fHello

原理分析




可以通过在application.yml
中更改默认文件夹和文件后缀名
freeMarker的指令和语法
基础语法
注释
<#-- -->
,介于其之间的内容会被freemarker
忽略
插值
${}
部分的内容,freemarker
会用真实值去替换
FTL指令
和html
中的标签类似,名字前加#以示区分,freemarker
会解析标签中的表达式或逻辑
文本
直接写的内容,是表示仅文本信息,这些内容不会被freemarker
解析,而是直接将内容输出
常用指令
集合指令—List
<#list></#list>
实例
Java代码
1 2 3 4 5 6 7 8
| @GetMapping("/fList") public String fList(Model model){ List<Student> list = new ArrayList<>(); list.add(new Student("李白",28,new Date(),27.92f)); list.add(new Student("曹操",68,new Date(),2007.92f)); model.addAttribute("stus",list); return "list"; }
|
模板内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <h2>学生信息列表</h2> <table> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>生日</th> <th>钱包</th> </tr> <#list stus as stu> <#--stu为stus里面的每一个元素 --> <tr> <td>${stu_index+1}</td> <#-- stu_index表示当前元素索引 --> <td>${stu.name}</td> <td>${stu.age}</td> <td>${stu.birthday?datetime}</td> <!-- 日期类型数据必须指定数据类型--> <td>${stu.money}</td> </tr> </#list> </table>
|
哈希数据—map
如何获取map里面元素的值
- 方式一:
map[keyname].properties
- 方式二:
map.keyname.properties
实例
1 2 3 4 5 6 7 8 9 10
| @GetMapping("/fMap") public String fMap(Model model){ Map<String,Student> map = new HashMap<>(); Student stu1 = new Student("李白",28,new Date(),27.92f); Student stu2 = new Student("曹操",68,new Date(),2007.92f); map.put("stu1",stu1); map.put("stu2",stu2); model.addAttribute("stusMap",map); return "map"; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| <h2>集合元素</h2> <hr/> <h4>学生1的信息</h4> <p>name:${stusMap.stu1.name}</p> <p>age:${stusMap.stu1.age}</p> <p>birthday:${stusMap.stu1.birthday?datetime}</p> <p>money:${stusMap.stu1.money}</p>
<h4>学生2的信息</h4> <p>name:${stusMap["stu2"].name}</p> <p>age:${stusMap["stu2"].age}</p> <p>birthday:${stusMap["stu2"].birthday?datetime}</p> <p>money:${stusMap["stu2"].money}</p>
|
遍历map
<#list>map?keys as key</#list>
map?keys
获取map
所有的键列表
实例
1 2 3 4 5 6 7 8 9 10
| @GetMapping("/fMapLsit") public String fMapList(Model model){ Map<String,Student> map = new HashMap<>(); Student stu1 = new Student("李白",28,new Date(),27.92f); Student stu2 = new Student("曹操",68,new Date(),2007.92f); map.put("stu1",stu1); map.put("stu2",stu2); model.addAttribute("stusMap",map); return "mapList"; }
|
1 2 3 4 5 6 7 8 9 10
| <h2>集合元素</h2> <hr/>
<#list stusMap?keys as key> <h4>学生${key_index+1}的信息</h4> <p>name:${stusMap[key].name}</p> <p>age:${stusMap[key].age}</p> <p>birthday:${stusMap[key].birthday?datetime}</p> <p>money:${stusMap[key].money}</p> </#list>
|
if指令
1 2 3 4 5
| <#if 条件语句>
<#else>
<#if>
|
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <h2>集合元素</h2> <hr/>
<#list stusMap?keys as key> <#if stusMap[key].age gte 40> <#-- 年龄大于40的用红色表示 --> <div style="color: red"> <h4>学生${key_index+1}的信息</h4> <p>name:${stusMap[key].name}</p> <p>age:${stusMap[key].age}</p> <p>birthday:${stusMap[key].birthday?datetime}</p> <p>money:${stusMap[key].money}</p> </div> <#else> <div> <h4>学生${key_index+1}的信息</h4> <p>name:${stusMap[key].name}</p> <p>age:${stusMap[key].age}</p> <p>birthday:${stusMap[key].birthday?datetime}</p> <p>money:${stusMap[key].money}</p> </div> </#if>
</#list>
|
运算符
算数运算符
- 加法:
+
- 减法:
-
- 乘法:
*
- 除法:
/
- 求模 (求余):
%
注意:
除了 + 运算以外,其他的运算只能和 number 数字类型的计算
比较运算符
=
或者==
:判断两个值是否相等.
!=
:判断两个值是否不等.
>
或者gt
:判断左边值是否大于右边值
>=
或者gte
:判断左边值是否大于等于右边值
<
或者lt
:判断左边值是否小于右边值
<=
或者lte
:判断左边值是否小于等于右边值
注意:
=
和!=
可以用于字符串、数值和日期来比较是否相等
=
和!=
两边必须是相同类型的值,否则会产生错误
- 字符串
"x"
、"x "
、"X"
比较是不等的.因为FreeMarker是精确比较
- 其它的运行符可以作用于数字和日期,但不能作用于字符串
- 使用
gt
等字母运算符代替>
会有更好的效果,因为 FreeMarker会把>
解释成FTL标签的结束字符
- 可以使用括号来避免这种情况,如:
<#if (x>y)>
逻辑运算符
注意:
逻辑运算符只能作用于布尔值,否则将产生错误
空值处理
判断某变量是否存在使用 ??
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <h2>集合元素</h2> <hr/>
<#if stusMap??> <#--判断stusMap是否存在--> <#list stusMap?keys as key> <#if (stusMap[key].age >= 40)> <div style="color: red"> <h4>学生${key_index+1}的信息</h4> <p>name:${stusMap[key].name}</p> <p>age:${stusMap[key].age}</p> <p>birthday:${stusMap[key].birthday?datetime}</p> <p>money:${stusMap[key].money}</p> </div> <#else> <div> <h4>学生${key_index+1}的信息</h4> <p>name:${stusMap[key].name}</p> <p>age:${stusMap[key].age}</p> <p>birthday:${stusMap[key].birthday?datetime}</p> <p>money:${stusMap[key].money}</p> </div> </#if>
</#list> </#if>
|
缺失变量默认值使用 !
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Hello World!</title> </head> <body> <#-- 注释部分 --> <b>普通文本 String 展示:</b><br><br> Hello ${name!'王虎'} <br> <#--当变量name不存在时,默认替换为王虎--> <hr> <b>对象Student中的数据展示:</b><br/> 姓名:${stu.name}<br/> 年龄:${stu.age} <hr> </body> </html>
|
内建函数
内建函数语法格式: 变量+?+函数名称
获取某个集合的大小
${集合名?size}
日期相关
显示年月日: ${today?date}
显示时分秒:${today?time}
显示日期+时间:${today?datetime}
自定义格式化: ${today?string("yyyy年MM月")}
内建函数c
model.addAttribute(“point”, 102920122);
point是数字型,使用${point}会显示这个数字的值,每三位使用逗号分隔。
如果不想显示为每三位分隔的数字,可以使用c函数将数字型转成字符串输出
${point?c}
将json字符串转成对象
text?eval
1 2 3 4
| <#-- assign的作用是创建一个新的变量 --> <#assign text="{'bank':'工商银行','account':'10101920201920212'}" /> <#assign data=text?eval /> 开户行:${data.bank} 账号:${data.account}
|
freeMaker静态文件生成
在mvc
中支持将freemarker
静态文件作为视图返回前端,但是在一些场景中,需要将生成的静态文件输出存储在本地
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package com.bang;
import com.bang.entity.Student; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Objects;
@SpringBootTest public class TestFreeMarker {
@Autowired private Configuration configuration;
@Test public void testGenerateFile() throws IOException, TemplateException { Template template = configuration.getTemplate("mapList.ftl"); Map<String, Student> map = new HashMap<>(); Student stu1 = new Student("李白",28,new Date(),27.92f); Student stu2 = new Student("曹操",68,new Date(),2007.92f); map.put("stu1",stu1); map.put("stu2",stu2);
Map<String, Object> params = new HashMap<>(); params.put("stusMap",map); template.process(params, new FileWriter("./test.html")); } }
|