FreeMarker
FreeMarker是一个模板引擎,就是一种基于模板和要改变的数据,并用来生成输出文本(HTML网页、配置文件、电子邮件等)的通用工具,是一个Java类库,是一个可以嵌入到开发项目中的一个组件
常见的模板引擎还有:
JSP
:Servlet
专用,不能单独使用Thymeleaf
: 新技术,功能强大,执行的效率比较低Velocity
: 很久没有更新,SpringBoot
官方在1.4版本后
也不再对其进行支持
入门案例
- 准备阶段:
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- freemarker起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
- 配置
FreeMarker
server:
port: 8899
spring:
application:
name: freemarker-demo
freemarker:
template-loader-path: classpath:/templates/ # freemarker模板的路径,默认就是classpath:/templates/ 在resources目录下创建templates
suffix: .ftl # freemarker模板文件后缀,默认是ftlh
-
准备模板
在
resources/templates
目录下新建模板文件,例(00-basic.ftl):
<!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
-
后端控制器
先准备个实体类:
@Data public class Student { private String name; private String age; private float money; private Date birthDay; }
准备
Controller
:@Controller // 因为返回的是一种字符串,不能返回json,不能用RestController public class HelloController { @GetMapping("/basic") public String hello(Model model) { model.addAttribute("name", "freemarker"); Student student = new Student(); student.setName("XLrong"); student.setAge("23"); student.setMoney(123.45F); model.addAttribute("stu", student); return "00-basic"; } }
-
测试
浏览器搜索:
http://localhost:8899/basic
,显示:
- 方式2
-
编写测试用例
@SpringBootTest(classes = FreeMarkerApp.class) @RunWith(SpringRunner.class) public class FreeMarkerTest { @Autowired Configuration configuration; // 和FreeMarker相关的包下 @Test public void freeMarkerTest() throws IOException, TemplateException { // 1. 获取模板 Template template = configuration.getTemplate("00-basic.ftl"); HashMap<String, Object> map = new HashMap<>(); map.put("name", "freemarker way2"); Student student = new Student(); student.setName("XLrong way2"); student.setAge("23 way2"); student.setMoney(111.11F); map.put("stu", student); // 2. 静态化 // 输出文件到什么地方 template.process(map, new FileWriter("D:/00-basic.html")); } }
- 测试
本地磁盘中有文件生成
打开html文件
FreeMarker语法
基本语法种类
-
注释:
<#-- -->
,介于其之间的内容会被FreeMarker
忽略<#-- This is a FreeMarker ex -->
-
插值:
${...}
,FreeMarker
会用真实的值代替${...}
,只使用插值,不做其他处理,但不传数据或者传空数据进,会报错${name}
-
FTL
指令: 和HTML
标记类似,名字前加#
予以区分,FreeMarker
会解析标签中的表达式或逻辑<#>FTL指令</#>
-
文本: 仅文本信息,这些不是
FreeMarker
的注释、插值、FTL
指令的内容会被FreeMarker
忽略解析,直接输出内容<#-- 普通文本 --> 普通文本
-
定义一个变量:
<#assign text="{'name':'XLrong','age':'23'}" />
集合指令
- 后端代码:
@GetMapping("/list")
public String list(Model model){
//------------------------------------
Student stu1 = new Student();
stu1.setName("小强");
stu1.setAge(18);
stu1.setMoney(1000.86f);
stu1.setBirthday(new Date());
//小红对象模型数据
Student stu2 = new Student();
stu2.setName("小红");
stu2.setMoney(200.1f);
stu2.setAge(19);
//将两个对象模型数据存放到List集合中
List<Student> stus = new ArrayList<>();
stus.add(stu1);
stus.add(stu2);
//向model中存放List集合数据
model.addAttribute("stus",stus);
//------------------------------------
//创建Map数据
HashMap<String,Student> stuMap = new HashMap<>();
stuMap.put("stu1",stu1);
stuMap.put("stu2",stu2);
// 3.1 向model中存放Map数据
model.addAttribute("stuMap", stuMap);
return "02-list";
}
- FTL模板:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<#-- list 数据的展示 -->
<b>展示list中的stu数据:</b>
<br>
<br>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list stus as stu>
<tr>
<#-- key_indes 表示该对象的下标,从零开始 -->
<td>${stu_index+1}</td>
<td>${stu.name}</td>
<td>${stu.age}</td>
<td>${stu.money}</td>
</tr>
</#list>
</table>
<hr>
<#-- Map 数据的展示 -->
<b>map数据的展示:</b>
<br/><br/>
<a href="###">方式一:通过map['keyname'].property</a><br/>
输出stu1的学生信息:<br/>
姓名:${stuMap['stu1'].name}<br/>
年龄:${stuMap['stu1'].age}<br/>
<br/>
<a href="###">方式二:通过map.keyname.property</a><br/>
输出stu2的学生信息:<br/>
姓名:${stuMap.stu2.name}<br/>
年龄:${stuMap.stu2.age}<br/>
<br/>
<a href="###">遍历map中两个学生信息:</a><br/>
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>钱包</td>
</tr>
<#list stuMap?keys as key >
<tr>
<td>${key_index}</td>
<td>${stuMap[key].name}</td>
<td>${stuMap[key].age}</td>
<td>${stuMap[key].money}</td>
</tr>
</#list>
</table>
<hr>
</body>
</html>
if指令
判断指令,常用的FTL指令,FreeMarker
在解析时遇到if会进行判断,条件为真时输出if中的内容,否则会跳过内容不再输出
指令格式:
<#if></if>
<#-- 实例 -->
<#if 条件1>
<#elseif 条件2>
<#elseif 条件3>
<#else>
<#/if>
运算符
- 加法:
+
- 减法:
-
- 乘法:
*
- 除法:
/
- 求模 (求余):
%
例:
<b>算数运算符</b>
<br/><br/>
100+5 运算: ${100 + 5}<br/>
100 - 5 * 5运算:${100 - 5 * 5}<br/>
5 / 2运算:${5 / 2}<br/>
12 % 10运算:${12 % 10}<br/>
<hr>
比较运算符
=
或者==
:判断两个值是否相等.!=
:判断两个值是否不等.>
或者gt
:判断左边值是否大于右边值>=
或者gte
:判断左边值是否大于等于右边值<
或者lt
:判断左边值是否小于右边值<=
或者lte
:判断左边值是否小于等于右边值
FTL
模板:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<b>比较运算符</b>
<br/>
<br/>
<dl>
<dt> =/== 和 != 比较:</dt>
<dd>
<#if "xiaoming" == "xiaoming">
字符串的比较 "xiaoming" == "xiaoming"
</#if>
</dd>
<dd>
<#if 10 != 100>
数值的比较 10 != 100
</#if>
</dd>
</dl>
<dl>
<dt>其他比较</dt>
<dd>
<#if 10 gt 5 >
形式一:使用特殊字符比较数值 10 gt 5
</#if>
</dd>
<dd>
<#-- 日期的比较需要通过?date将属性转为data类型才能进行比较 -->
<#if (date1?date >= date2?date)>
形式二:使用括号形式比较时间 date1?date >= date2?date
</#if>
</dd>
</dl>
<br/>
<hr>
</body>
</html>
注:
=
和!=
可以用于字符串、数值和日期来比较是否相等=
和!=
两边必须是相同类型的值,否则会产生错误- 字符串
"x"
、"x "
、**"X"
**比较是不等的.因为FreeMarker是精确比较 - 其它的运行符可以作用于数字和日期,但不能作用于字符串
- 使用**
gt
等字母运算符代替>
会有更好的效果,因为 FreeMarker会把>
**解释成FTL标签的结束字符 - 可以使用括号来避免这种情况,如:
<#if (x>y)>
逻辑运算符
- 逻辑与:&&
- 逻辑或:||
- 逻辑非:!
注: 逻辑运算符只能作用于布尔类型,否则会报错
FTL
模板:
<b>逻辑运算符</b>
<br/>
<br/>
<#if (10 lt 12 )&&( 10 gt 5 ) >
(10 lt 12 )&&( 10 gt 5 ) 显示为 true
</#if>
<br/>
<br/>
<#if !false>
false 取反为true
</#if>
<hr>
空值处理
- 判断某变量是否存在时使用
??
<#if stus??>
<#list stus as stu>
......
</#list>
</#if>
- 缺失变量默认值使用
!
<#-- 如果name为空则赋空字符串 -->
${name!''}
如果是嵌套对象则建议使用()
括起来
${(stu.bestFriend.name)!''}
内建函数
基础语法: 变量 ? 函数名称
-
得到某个集合的大小:
${集合名?size}
-
日期格式化
- 显示年月日:
${today?date}
- 显示时分秒:
${today?time}
- 显示日期+时间:
${today?datetime}
- 自定义格式化:
${today?string("yyyy年MM月")}
- 显示年月日:
-
FreeMarker
显示数字类型是会将数字以三位字符用逗号隔开,使用内建函数c
可以将数字型转换为字符串类型:${point?c}
-
将字符串转换为对象:
<#assign text="{'name':'XLrong','age':'23'}" /> <#assign data=text?eval />