文章目录
一、FreeMarker简介
FreeMarker是一款模板引擎,Freemarker 模版后缀为 .ftl(FreeMarker Template Language)。FTL 是一种简单的、专用的语言,它不是像 PHP那样成熟的编程语言。在模板中,你可以专注于如何展现数据, 而在模板之外可以专注于要展示什么数据。
这种方式通常被称为 MVC (模型 视图 控制器) 模式,对于动态网页来说,是一种特别流行的模式。
特点:
- 轻量级模版引擎,不需要Servlet环境就可以很轻松的嵌入到应用程序中
- 能生成各种文本,如html,xml,java,等
- 入门简单,它是用java编写的,很多语法和java相似
二、Spring Boot整合FreeMarker
1.添加依赖
在IDEA中创建Spring Boot项目时,添加FreeMarker和web依赖。
在已创建好的项目可以直接在pom.xml中添加以下代码,添加FreeMarker依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2.相关配置
我们可以在application.properties中进行配置,没有设置的属性则按默认的使用,常见的配置如下:
#设置HttpServletRequest的属性是否覆盖controller中的mode的同名项
spring.freemarker.allow-request-override=false
#设置HttpSession的属性是否覆盖controller中的mode的同名项
spring.freemarker.allow-session-override=false
#是否开启缓存
spring.freemarker.cache=false
#设置模板文件编码
spring.freemarker.charset=UTF-8
#设置模板的位置
spring.freemarker.check-template-location=true
#设置模板文件的内容格式
spring.freemarker.content-type=text/html
#是否将HttpServletRequest中的属性添加到Model中
spring.freemarker.expose-request-attributes=false
#是否将HttpServletRequest中的属性添加到Model中
spring.freemarker.expose-session-attributes=false
#设置模板文件后缀
spring.freemarker.suffix=.ftl
#设置模板文件位置
spring.freemarker.template-loader-path=classpath:/templates/
3.FreeMarker文件模板
因为IDEA没有提供FreeMarker文件模板,所以我们可以创建一个以方便后续使用。
项目中任意地方右击:New->File->Edit File Templates,进入如下页面:
然后更改文件名和文件类型
点击OK就完成了ftl的文件模板的创建。创建FTL File如下:
这样就完成了在Spring Boot项目中整合FreeMarker。
三、简单使用示例
在上面创建好的Spring Boot项目中创建一个User类
@Component
public class User {
private long id;
private String username;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
创建一个UserController类:
@Controller
public class UserController {
@GetMapping("/show")
public String show(Model model){
List<User> users=new ArrayList<User>();
for (int i = 0; i < 10; i++) {
User user=new User();
user.setId(i);
user.setUsername("用户"+i);
users.add(user);
}
model.addAttribute("users",users);
return "show";
}
}
在templates中创建一个show.ftl:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>用户编号</td>
<td>用户名称</td>
</tr>
<#list users as user>
<tr>
<td>${user.id}</td>
<td>${user.username}</td>
</tr>
</#list>
</table>
</body>
</html>
项目目录如下:
启动项目,在浏览器中访问:
四、FreeMarker常用指令
(一)assign指令
assign指令用于为该模板页面创建变量或替换一个顶层变量,其语法格式下:
<#assign name1=value1 name2=value2 ... nameN=valueN>
或
<#assign same as above... in namespacehash>
或
<#assign name>
capture this
</#assign>
或
<#assign name in namespacehash>
capture this
</#assign>
语法:
- name:变量的名字。 它不是表达式。它可以写作是字符串,如果变量名包含保留字符这是很有用的, 比如 <#assign “foo-bar” = 1>。 请注意这个字符串没有展开插值(如"${foo}"); 如果需要赋值一个动态创建的名字,那么不得不使用 这个技巧。
- =:赋值操作符。 它也可以是一个简写的赋值操作符(从 FreeMarker 2.3.23 版本开始): ++,–, +=,-=, *=,/= 或 %=。比如 <#assign x++> 和 <#assign x = x + 1> 是一样的,并且 <#assign x += 2> 和 <#assign x = x + 2> 是相同的。 请注意, ++ 通常意味着算术加法 (对于非数字将会失败),不像 + 或 += 可以进行字符连接等重载操作。
- value: 存储的值。是表达式。
- namespacehash:(通过 import) 为命名空间创建的哈希表。是表达式。
例子:
<#assign week=["星期一","星期二","星期三","星期四","星期五"]>
<#list week as day>
${day}
</#list>
在命名空间 /mylib.ftl 中创建/替换了变量 bgColor:
<#import "/mylib.ftl" as my>
<#assign bgColor="red" in my>
注意我们不能使用assign指令在字符串中插入变量:
<#assign x>Hello ${user}!</#assign> <#-- BAD PRACTICE! -->
应该这么写:
<#assign x="Hello ${user}!">
(二)if指令
这是一个典型的分支控制指令,该指令的作用类似Java语言中的if,if指令的语法格式如下:
<#if condition>
...
<#elseif condition2>
...
<#elseif condition3>
...
...
<#else>
...
</#if>
语法:
- condition 必须计算成布尔值, 否则错误将会中止模板处理
- elseif 和 else 必须出现在 if 内部 (也就是,在 if 的开始标签和结束标签之间)。
- if 中可以包含任意数量的 elseif(包括0个) 而且结束时 else 是可选的
注意:如果编写 <#if x > 0> 和 <#if x >= 0> 是错误的, 因为第一个 > 会结束 #if 标签。所以比较要写在括号内,如<#if (x > 0))> 和 <#if (x >= 0)>
例子:
<#assign age=23>
<#if (age>60)>老年人
<#elseif (age>30)>中年人
<#elseif (age>20)>青少年
<#else>老年人
</#if>
(三)分支指令
分支指令包括:switch、case、default、break。作用类似java语法,分支指令的语法结构下:
<#switch value>
<#case refValue1>
...
<#break>
<#case refValue2>
...
<#break>
...
<#case refValueN>
...
<#break>
<#default>
...
</#switch>
语法:
- value, refValue1,等: 表达式将会计算成相同类型的标量。
- break 和 default 是可选的。
例子:
<#assign gender=1>
<#switch gender>
<#case 0>女性
<#break>
<#case 1>男性
<#break>
<#default>未知
</#switch>
(四)list指令
list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:
<#list sequence as item>
Part repeated for each item
<#else>
Part executed when there are 0 items
</#list>
语法:
- sequence:可以是一个集合对象或表达式(返回一个集合对象的表达式)
- item:循环变量的名称
- 此外,迭代集合对象时还包含两个特殊的循环变量:(出于向后兼容考虑,它们仍然能使用)
item_index(已废弃,由item?index代替):当前变量的索引值,从0开始的数字
item_has_next(已废弃,由item?has_next代替):辨别当前项是否是序列的最后一项的布尔值。 - 可以使用<#break>指令跳出迭代
例子:
<#list ["星期一","星期二","星期三","星期四","星期五","星期六"] as x>
${x_index+1}.${x}<#if x_has_next>,</#if>
<#if x_index=4><#break></#if>
</#list>
(五)include指令
include指令的作用类似于JSP的包含指令,用于包含指定页。其语法格式如下:
<#include path>
或
<#include path options>
语法:
- path: 要包含文件的路径;一个算作是字符串的表达式。(用其他话说, 它不用是一个固定的字符串,它也可以是像 profile.baseDir + "/menu.ftl"这样的东西。)
- options: 一个或多个这样的选项: encoding=encoding, parse=parse
支持options选项有:
-
parse:如果它为 true, 那么被包含的文件将会当作FTL来解析,否则整个文件将被视为简单文本 (也就是说不会在其中查找 FreeMarker 的结构)。如果你忽略了这个选项, 那么它默认是 true。
-
encoding:被包含文件从包含它的文件继承的编码方式 (实际就是字符集),除非你用这个选项来指定编码方式。 合法的名字有:ISO-8859-2,UTF-8,Shift_JIS,Big5,EUC-KR,GB2312。 编码名称要和java.io.InputStreamReader 中支持的那些一致。
-
ignore_missing:当为 true,模板引用为空时压制错误,而 <#include …> 不会输出任何东西。当为 false 时,如果模板不存在, 那么模板处理就会发生错误并停止。如果忽略这个选项,那么它的默认值是 false。
注意:通常使用 /(斜杠)来分隔路径成分, 而不是 (反斜杠)。如果你从你本地的文件系统加载模板, 而它使用反斜杠(像Windows操作系统),也要使用 /
例子:
在template目录下创建一个header.ftl,内容为:
<h1>我是头部栏!</h1>
然后在show.ftl的body标签中使用此指令引入:
<#include "*/header.ftl" encoding="UTF-8" ignore_missing=true >
浏览器中访问:
(六)import指令
该指令用于导入FreeMarker模板中的所有变量,并将该变量放置到指定的Map对象中,import指令的语法格式如下:
<#import path as hash>
语法
- path:模板的路径。 这是一个算作是字符串的表达式。比如,profile.baseDir + “/menu.ftl”。
- hash: 访问命名空间的哈希表变量不带引号的名字。不是表达式。
例如,使用了<#import /lib/menu.ftl as data>, /lib/menu.ftl模板文件中的所有变量将放置到一个名为data的Map对象中。
(七)noparse指令
noparse指令指定FreeMarker不会在这个指令体中间寻找FTL标签,插值和其他特殊的字符序列,除了noparse的结束标记。语法格式如下:
<#noparse>
...
</#noparse>
例子:
<#noparse>
<#将动物列为动物>
<tr> <td> $ {animal.name} <td> $ {animal.price}欧元
</#list>
</#noparse>
输出:
<#将动物列为动物>
<tr> <td> $ {animal.name} <td> $ {animal.price}欧元
</#list>
如果要进一步地学习FreeMarker,可以看:
FreeMarker在线手册
https://segmentfault.com/a/1190000008770449