FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:
1. 文本:直接输出的部分
1. 注释:<#– … –>格式部分,不会输出
1. 插值:即${…}或#{…}格式的部分,将使用数据模型中的部分替代输出
1. FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出
常用指令
if指令
if指令进行条件输出控制,类似程序语言中的if语句。
<#if username == "boss">Hi boss!</#if>
<#if username == "boss">Hi boss!<#else>Hi!</#if>
switch , case , default , break指令
这些指令显然是分支指令,作用类似于Java的switch语句,switch指令的语法结构如下:
<#switch value>
<#case refValue>...<#break>
<#case refValue>...<#break>
<#default>...
</#switch>
assign指令
assign指令用来定义一个变量并给其赋值,或者替换原有变量的值
<#assign username="master">
include指令
使用include指令,我们可以在当前的模板中插入其他文件的内容。
<#include "/copyright_footer.html">
被包含进来的文件,既可以是静态页,也可以是动态页(即ftl模板)。include指令会先将该文件内容包含进当前模板,然后再跟数据模型结合输出。
noparse指令
noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:
<#noparse>…
<#noparse>
<#list books as book>
<tr><td>${book.name}<td>作者:${book.author}
</#list>
</#noparse>
输出如下:
<#list books as book>
<tr><td>${book.name}<td>作者:${book.author}
</#list>
setting指令
该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
- locale:该选项指定该模板所用的国家/语言选项
- number_format:指定格式化输出数字的格式
- boolean_format:指定两个布尔值的语法格式,默认值是true,false
- date_format,time_format,datetime_format:指定格式化输出日期的格式
- time_zone:设置格式化输出日期时所使用的时区
macro , nested , return指令
macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:
<#macro name param1 param2 ... paramN>
...
<#nested loopvar1, loopvar2, ..., loopvarN>
...
<#return>
...
</#macro>
在上面的格式片段中,包含了如下几个部分:
name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
nested指令:nested标签输出使用自定义指令时的中间部分
nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板
return指令:该指令可用于随时结束该自定义指令.
看如下的例子:
<#macro book> //定义一个自定义指令
j2ee
</#macro>
<@book /> //使用刚才定义的指令
上面的代码输出结果为:j2ee
在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:
<#macro book booklist> //定义一个自定义指令booklist是参数
<#list booklist as book>
${book}
</#list>
</#macro>
<@book booklist=["spring","j2ee"] /> //使用刚刚定义的指令
上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:spring j2ee
t, lt, rt
- t (整体削减):忽略本行中首和尾的所有空白。
- lt (左侧削减):忽略本行中首部所有的空白。
- rt (右侧削减):忽略本行中尾部所有的空白。
例如
1 <#t>
2<#t>
3<#lt>
4
5<#rt>
6
将会输出
1 23
4
5 6
数字格式化插值
数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:
- mX:小数部分最小X位
- MX:小数部分最大X位
如下面的例子:
<#assign x=2.582/>
<#assign y=4/>
#{x; M2} <#-- 输出2.58 -->
#{y; M2} <#-- 输出4 -->
#{x; m2} <#-- 输出2.6 -->
#{y; m2} <#-- 输出4.0 -->
#{x; m1M2} <#-- 输出2.58 -->
#{x; m1M2} <#-- 输出4.0 -->
Map连接运算符
Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:
<#assign scores = {"语文":86,"数学":78} + {"数学":87,"Java":93}>
语文成绩是scores.语文数学成绩是{scores.数学}
Java成绩是${scores.Java}
输出结果是:
语文成绩是86
数学成绩是87
Java成绩是93
算术运算符
FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , % 看如下的代码:
<#assign x=5>
${ x * x - 100 }
${ x /2 }
${ 12 %10 }
输出结果是:
-75 2.5 2
在表达式中使用算术运算符时要注意以下几点:
1. 运算符两边的运算数字必须是数字
1. 使用+运算符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串再连接,如:${3 + “5”},结果是:35
使用内建的int函数可对数值取整,如:
<#assign x=5>
${ (x/2)?int }
${ 1.1?int }
${ 1.999?int }
${ -1.1?int }
${ -1.999?int }
结果是:2 1 1 -1 -1
字符串内建函数
FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来轮换输出变量.下面是常用的内建的字符串函数:
1. html:对字符串进行HTML编码
1. cap_first:使字符串第一个字母大写 例:var?cap_first
1. lower_case:将字符串转换成小写 例:var?lower_case
1. upper_case:将字符串转换成大写 例:var?upper_case
1. trim:去掉字符串前后的空白字符 例:var?trim
2. length:获取字符串长度 例:var?length
3. capitalize:每个单词的首字符大写 例:var?capitalize
4. contains如果函数中的参数指定的子串出现在源字符串中, 那么返回true。比如:
<#if "piceous"?contains("ice")>It contains "ice"</#if>
out It contains "ice"
- split:它被用来根据另外一个字符串的出现将原字符串分割成字符串序列。 比如:
<#list "someMOOtestMOOtext"?split("MOO") as x>
${x}
</#list>
输出
some
test
text
日期内建函数
- date, time, datetime (当用于日期/时间/日期-时间值时)
- date:仅日期部分,没有一天当中的时间部分。
- time:仅一天当中的时间部分,没有日期部分。
- datetime:日期和时间都在
- string (当用于日期/时间/日期-时间值时)
${lastUpdated?string["dd.MM.yyyy, HH:mm"]}
${lastUpdated?string["EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'"]}
${lastUpdated?string["EEE, MMM d, ''yy"]}
${lastUpdated?string.yyyy} <#-- Same as ${lastUpdated?string["yyyy"]} -->
将输出
08.04.2003 21:24
Tuesday, April 08, 2003, 09:24 PM (PDT)
Tue, Apr 8, '03
2003
布尔内建函数
- then
<#assign foo = true>
${foo?then('Y', 'N')}
<#assign foo = false>
${foo?then('Y', 'N')}
<#assign x = 10>
<#assign y = 20>
<#-- Prints 100 plus the maximum of x and y: -->
${100 + (x > y)?then(x, y)}
输出
Y
N
120
序列内建函数
- join:使用给定的分隔符来连接序列中的项为一个独立的字符串
<#assign colors = ["red", "green", "blue"]>
${colors?join(", ")}
输出
red, green, blue
- seq_contains:辨别序列中是否包含指定值。它包含一个参数,就是来查找的值
<#assign x = ["red", 16, "blue", "cyan"]>
"blue": ${x?seq_contains("blue")?string("yes", "no")}
"yellow": ${x?seq_contains("yellow")?string("yes", "no")}
16: ${x?seq_contains(16)?string("yes", "no")}
"16": ${x?seq_contains("16")?string("yes", "no")}
输出
"blue": yes
"yellow": no
16: yes
"16": no
- size:获取序列中元素的个数
哈希表内建函数
- keys
<#assign h = {"name":"mouse", "price":50}>
<#assign keys = h?keys>
<#list keys as key>${key} = ${h[key]}; </#list>
输出
name = mouse; price = 50;
- values:一个包含哈希表中子变量的序列。 注意并不是所有的哈希表都支持这个 ,至于返回的值的顺序,和内建函数 keys 的应用是一样的;看看上面的叙述就行了。
循环变量内建函数
- counter:返回当前迭代(由循环变量名称识别)从1开始的索引。
<#list ['a', 'b', 'c'] as i>
${i?counter}: ${i}
</#list>
输出
1: a
2: b
3: c
- index:返回当前迭代(由循环变量名称识别)从0开始的索引。
<#list ['a', 'b', 'c'] as i>
${i?index}: ${i}
</#list>
输出
0: a
1: b
2: c
- is_first:辨别循环项是否是当前迭代(由循环变量名称识别)的第一项。
<#list ['a', 'b', 'c'] as i>${i?is_first?c} </#list>
输出
true false false
- is_last:辨别循环项是否是当前迭代(由循环变量名称识别)的最后一项。
<#list ['a', 'b', 'c'] as i>${i?is_last?c} </#list>
输出
false false true
空值处理运算符
FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的 null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同.
为了处理缺失变量,FreeMarker提供了两个运算符:
- !:指定缺失变量的默认值
- ??:判断某个变量是否存在
其中,!运算符的用法有如下两种:
variable!或variable!defaultValue,第一种用法不给缺失的变量指定默认值,表明默认值是空字符串,长度为0的集合,或者长度为0的Map对象.
使用!指定默认值时,并不要求默认值的类型和变量类型相同.使用??运算符非常简单,它总是返回一个布尔值,用法为:variable??,如果该变量存在,返回true,否则返回false