[TOC]
模板一览
符号 | 注释 |
---|---|
${...} | 输出真实的值来替换花括号内的表达式 |
#开头 | FTL标签,是指令,且不会直接输出来的东西,用户自定义为@ |
<#-- --> | FTL注释,其它任何不是FTL标签,插值或注释的内容将被视为静态文本 |
指令示例
if指令
<#if condition></#if>
<h1>
Welcome ${user}<#if user = "Big Joe">, our beloved leader</#if>!
</h1>
list指令
<#list sequence as loopVariable>repeatThis</#list>
repeatThis部分将会在给定的sequence遍历时在每项中重复,从第一项开始,一个接着一个。
在所有的重复中,loopVariable将持有当前项的值。这个循环变量仅存在于<#list ...>和</#list>
标签之间
<#list whatnot.fruits as fruit>
<li>${fruit}
</#list>
include指令
使用include指令,我们可以在当前的模板中插入其它文件的内容。
<#include "/copyright_footer.html">
处理不存在的变量
Freemarker不能容忍引用不存在的变量,除非明确告诉它当变量不存在时如何处理,这里介绍
两种方案
- 不论在哪里引用变量,都可以指定一个默认值来避免丢失这种情况,通过在变量名后面跟着
一个!和默认值,
<h1>Welcome ${user !"Anonymous"}!</h1>
- 在变量名后面通过放置??来询问Freemarker一个变量是否存在,将它和if指令合并,那么如果
变量不存在的话将会忽略整个问候代码段
<#if user??><h1>Welcome ${user}!</h1></#if>
关于多级访问的变量,比如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)??来看。
数据类型
简介
支持的类型有
- 标量
- 字符串
- 数字
- 布尔值
- 日期
- 容器
- 哈希表
- 序列
- 集
- 子程序
- 方法和函数
- 用户自定义指令
- 其它/很少使用
- 节点
模板
总体结构
- 插值仅仅可以在文本中间使用(也可以在字符串表达式中)
- FTL标签不可以在其它FTL标签和插值中使用
- 注释可以放在FTL标签和插值中间
预定义指令和用户自定义指令区别: - 用户自定义指令使用@来代替#
- 如果指令没有嵌套内容,那么必须使用<@mydirective parameters/>
表达式
快速浏览(备忘单)
- 直接指定值
- 字符串 "Foo", 'Foo', " It's "quoted" "
- 数字 124.44
- 布尔值 true,false
- 序列 ["Foo", "bar", 2323], 1 .. 100
- 哈希表 {"name":"newcih", "price":233}
- 检索变量
- 顶层变量 user
- 从哈希表中检索数据 user.name 或者 user["name"]
- 从序列中检索 products[5]
- 特殊变量 .main
- 字符串操作
- 插值(或连接) "Hello ${user}!" 或者 ("Free"+"Marker")
- 获取一个字符 name[0]
- 序列操作
- 连接 users+["guest"]
- 序列切分 products[10 .. 19] 或 products[5 ..]
- 哈希表操作
- 连接 passwords + {"joe":"secret42""}
- 算数运算 (x5.2+19)*
- 比较运算 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)??
字符串
在原生字符串中,反斜杠和${没有特殊的含义,它们被视为普通的字符。为了表明字符串是原生字符串,
在开始的引号或单引号之前放置字母r,例如
${r"${foo}"}
将会打印${foo}
数字
- 不支持科学计数法
- 小数点前要写0
布尔值
直接写true或false,不加引号
序列
使用逗号来分隔其中的每个子变量,然后把整个列表放到方括号中
<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>
也可以使用start .. end定义存储数字范围的序列,比如 2 .. 5和[2,3,4,5]是相同的,但是前者更有效率
检索变量
为了访问顶层变量,可以简单的使用变量名
${user}
从序列中检索数据
animals[0].name
特殊变量
由Freemarker引擎本身自定义的,为了使用它们,可以按照如下语法形式来进行
.variable_name
通常情况下是不需使用特殊变量,而对专业用户来说可能用到
字符串操作
插值
如果要在字符串中插入表达式的值,可以在字符串的文字中使用${...}(#{...})
${"Hello ${user}!"}
或${"Hello"+user}
插值只能在文本区段和字符串文字中使用,不能在if标签使用,因为if标签需要布尔值
序列操作
连接
序列的连接可以使用+号来进行
比较操作
使用>=和>的时候有一点小问题,Freemarker解释>的时候会把它当做FTL标签的结束符。为了
避免这种问题,不得不将表达式放到括号里
<#if (x > y)></#if>
或者使用>和<(通常在FTL标签中不支持实体引用(比如&...;这些),否则就会抛出算数比较异常)
另外也可以用lt代替<,lte代替<=,gt代替>,gte代替>=。
内建函数
- 字符串使用的内建函数
- html 字符串中所有的特殊HTML字符都需要用实体引用来替代(比如<代替<)
- cap_first 字符串的第一个字母变为大写形式
- lower_case 字符串的小写形式
- upper_case 字符串的大写形式
- trim 去掉字符串首尾的空格
- 序列使用的内建函数
- size 序列中元素的个数
- 数字使用的内建函数
- int 数字的整数部分
${test?html}
${test?upper_case?html}
方法调用
可以使用方法调用操作来使用一个已经定义过的方法。方法调用的语法形式是使用逗号来分割在括号内
的表达式而形成的参数列表。假设程序员定义了一个可供调用的方法repeat。第一个参数字符串类型,
第二个参数是数字类型。
${repeat("what", 3)}
默认值
模板语言没有null这个概念,如果属性的值是null,和不存在这个属性的情况是一致的。调用方法的返回值
如果是null的话,Freemarker也会把它当做不存在的变量来处理。以下默认值的使用形式
unsafe_expr!default_expr
unsafe_expr!
(unsafe_expr)!default_expr
(unsafe_expr)!
例如
${mouse!"No mouse."}
默认值可以是任何类型的表达式,也可以不必是字符串。你也可以这么写
hits!0
colors!["red", "green"]
插值
插值表达式的结果必须是字符串,数字或日期类型的,因为只有数字和日期类型可以自动转换为字符串类型,
其他类型的值(如布尔,序列)只能手动转换为字符串类型,否则就会发生错误
字符串插入指南,不要忘了转义,如果插值在文本区(也就是说,不在字符串表达式中),如果escapse指令起作用了,
即将被插入的字符串会被自动转义。如果你要生成HTML,那么强烈建议你利用它来阻止跨站脚本攻击和非格式良好
的HTML页面
<#escape x as x?html>
...
<p>Title:${book.title}</p>
<#noescape>${book.description}</#noescape>
</#escape>
网友评论