处理不存在的变量
当 user 从数据模型中丢失时,模板将会将
user 的值表示为字符串”Anonymous”。(若 user 并没有丢失,那么模板就会表现
出”Anonymous”不存在一样):
当然也可以在变量名后面通过放置??来询问 FreeMarker 一个变量是否存在。将它和 if
指令合并,那么如果 user 变量不存在的话将会忽略整个问候代码段:
关于多级访问的变量,比如 animals.python.price ,书写代码:
animals.python.price!0,仅当 animals.python 存在而仅仅最后一个子变
量 price 可能不存在(这种情况下我们假设价格是 0) 。如果 animals 或者 python
不存在,那么模板处理过程将会以“未定义的变量”错误而停止。 为了防止这种情况的发生,
可以这样来书写代码(animals.python.price)!0。这种情况下当 animals 或
python 不存在时表达式的结果仍然是 0。对于??也是同样用来的处理这种逻辑的:
animals.python.price??对比(animals.python.price)??来看。
用户自定义指令
假设现在有一个变量,box,它的值是用户自定义的指令,用来打印一些特定的 HTML 信息,
这个指令定义了一个标题和其中的信息。
<@box title="Attention!">
Too much copy-pasting may leads to
maintenance headaches.
</@box>
注释:
<#-- Greet the user with his/her name -->
换行:
[BR]
FTL 是区分大小写的。list 是指令的名称而 List 就不是,类似地${name}和
${Name}或者${NAME}它们也是不同的。
应该意识到非常重要的一点:插值仅仅可以在文本中间使用(也可以在字符串表达式
中,后续将会介绍) 。
FTL 标签不可以在其他 FTL 标签和插值中使用。下面这样写就是错的:
<#if <#include 'foo'>='bar'>...</#if>
注释可以放在 FTL 标签和插值中间。
一些空格、制表符
和换行符从模板输出中都不见了,尽管我们之前已经说了文本是按照原样输出的。 现在不用
为此而计较,这是由于 FreeMarker 的“空格剥离”特性在起作用,它当然会自动去除一些
多余的空格,制表符和换行符了。
使用 FTL 标签来调用 directives 指令,比如调用 list 指令。在语法上我们使用了两个标
签:<#list animals as being>和</#list>
标签分为两种:
开始标签:<#directivename parametes>
结束标签:</#directivename>
指令有两种类型:预定义指令和用户自定义指令。对于用户自定义的指令使用
@来代替#,比如<@mydirective parameters>...</@mydirective>。更深
的区别在于如果指令没有嵌套内容,那么必须这么使用 <@mydirective
parameters />
快速浏览(备忘单)
这里是给已经了解 FreeMarker 的人或有经验的程序员的一个提醒:
直接指定值
字符串:"Foo" 或者 'Foo' 或者 "It's \"quoted\"" 或者
r"C:\raw\string"
数字:123.45
<#list[BR]
animals as[BR]
being[BR]
>[BR]
${being.name} for ${being.price} Euros[BR]
</#list > 布尔值:true, false
序列:["foo", "bar", 123.45], 1..100
哈希表:{"name":"green mouse", "price":150}
检索变量
顶层变量:user
从哈希表中检索数据:user.name, user[“name”]
从序列中检索:products[5]
特殊变量:.main
字符串操作
插值(或连接):"Hello ${user}!"(或"Free" + "Marker")
获取一个字符:name[0]
序列操作
连接:users + ["guest"]
序列切分:products[10..19] 或 products[5..]
哈希表操作
连接:passwords + {"joe":"secret42"}
算数运算: (x * 1.5 + 10) / 2 - y % 100
比较 运算 : x == y, x != y, x < y, x > y, x >= y, x <= y,
x < y, 等等
逻辑操作:!registered && (firstVisit || fromEurope)
内建函数:name?upper_case
方法调用:repeat("What", 3)
处理不存在的值
默认值:name!"unknown" 或者(user.name)!"unknown" 或者
name! 或者 (user.name)!
检测不存在的值:name?? 或者(user.name)??
参考:运算符的优先级
下面的表格是 FreeMarker 支持的所有转义字符。在字符串使用反斜杠的其他所有情况
都是错误的,运行这样的模板都会失败。
转义序列 含义
\ 引号(u0022)
\’ 单引号(又称为撇号)(u0027)
\\ 反斜杠(u005C)
\n 换行符(u000A)
\r 回车(u000D)
\t 水平制表符(又称为标签)(u0009)
\b 退格(u0008)
\f 换页(u000C)
\l 小于号:<
\g 大于号:>
\a 和号:&
\xCode 字符的 16 进制 Unicode 码(UCS 码)
一种特殊的字符串就是原生字符串。在原生字符串中,反斜杠和${没有特殊的含义,
它们被视为普通的字符。为了表明字符串是原生字符串,在开始的引号或单引号之前放置字
母 r,例如:
${r"${foo}"}
${r"C:\foo\bar"}
将会打印:
${foo}
C:\foo\bar
从哈希表中检索数据
如果有一个表达式的结果是哈希表,那么我们可以使用点和子变量的名字得到它的值,
假设我们有如下的数据模型:
(root)
|
+- book
| |
| +- title = "Breeding green mouses"
| |
| +- author
| |
| +- name = "Julia Smith"
| |
| +- info = "Biologist, 1923-1985, Canada"
通常来说,FreeMarker 不会自动将字符串转换为数字,反之会自动进行。
有时我们只想获取计算结果的整数部分,这可以使用内建函数 int 来解决。
仍然假设 x 的值是 5,那么将会输出:
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}
2
1
1
-1
-1
比较运算
对数字和日期类型的比较,也可以使用<,<=,>=和>。不能把它们当作字符串来比
较。比如:
<#if x <= 12>
x is less or equivalent with 12
</#if>
使用>=和>的时候有一点小问题。FreeMarker 解释>的时候可以把它当作 FTL 标签的结
束符。为了避免这种问题,不得不将表达式放到括号内:<#if (x > y)>,或者可以在
比较关系处使用>和<:<#if x > y>。(通常在 FLT 标签中不支持实体引
用(比如&...;这些),否则就会抛出算数比较异常) 。另外,可以使用 lt 代替<,lte
代替<=, gt 代替>, gte 代替>=, 由于历史遗留的原因, FTL 也支持\lt, \lte, \gt 和
\gte,使用他们和使用不带反斜杠的效果一样。