// FTL 标签(eg:<#if>) 不可以在其他 FTL 标签 和 插值(${xxx})中使用
${a} 取a变量的值。 ${avg(6, 10, 20)} FTL区分大小写的
// user.name, user["name"] products[5]
<#if user == "Big Joe">
//
<#elseif animals.elephant.price < animals.python.price>
//
<#else>
//
</#if>
<#list animals as animal>
<#sep>,</#sep> //只有还有下一项的时候才会执行
<#else>None //当animals为空的时候 会显示这里。None
</#list>
<#list misc.fruits>
<ul>
<#items as fruit> //这样,当fruits为空时,不会显示<ul></ul>
<li>${fruit}
</#items>
</ul>
</#list>
<#include "/copyright_footer.html"> //将copyright_footer.html页面源码插入当前页面
### 使用内建函数 对象 + ? + 函数名
user?upper_case?html
fruits?join(", ")
user?starts_with("J")
### 处理不存在的变量
<h1>Welcome ${user!"visitor"}!</h1> //当user为空的时候显示visitor ! 当前面不存在时用后面的替换
// 默认值: name!"unknown" 或者 (user.name)!"unknown" 或者 name! 或者 (user.name)!
<#if user??><h1>Welcome ${user}!</h1></#if>。 // ??来询问一个变量是否存在 返回 true false
## 字符串切分:
包含结尾: name[0..4],不包含结尾: name[0..<5]
基于长度(宽容处理): name[0..*5],去除开头: name[5..]
## 值域:
start..<end // start,start+1,....,end-1
start..end // start,start+1,....,end
start..*length // 10..*4 [10, 11, 12, 13] 10..*-4 [10, 9, 8, 7] 10..*0 []
start.. // start ........
## 方法调用
${repeat("Foo", 3)} //程序员定义了一个可供调用的方法 repeat
## 赋值操作符 assign, local 和 global
<#assign x *= y>
## 自定义指令 可以包含插值 和 FTL标签 ( 宏 调用)
定义:
<#macro greet>
<font size="+2">Hello Joe!</font>
</#macro>
使用:
<@greet></@greet> or <@greet/>
定义:
<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>
使用:
<@greet person="Fred"/> // = 后面可以是 FTL表达式
// 多个参数。<#macro greet person color="default"> <@greet person="Fred" color="black"/>
## 嵌套内容
定义:
<#macro border>
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
使用: <#nested>被替换为 The bordered text nested中的代码段,访问不到定义的局部变量
<@border>The bordered text</@border>
定义:
<#macro repeat count>
<#list 1..count as x>
<#nested x, x/2, x==count>
</#list>
</#macro>
<@repeat count=4 ; c, halfc, last>
${c}. ${halfc}<#if last> Last!</#if>
</@repeat>
使用:; 后面的为参数表,对应作为nested的参数。 c->x halfc->x/2 last->x==count
## 在模板中定义变量
1. ''简单''变量: 它能从模板中的任何位置来访问,或者从使用 include 指令引入的模板访问。可以使用 assign 指令来创建或替换这些变量。因为宏和方法只是变量,那么 macro 指令 和 function 指令 也可以用来设置变量,就像 assign 那样。
2. 局部变量:它们只能被设置在 宏定义体内,而且只在宏内可见。一个局部变量的生命周期只是宏的调用过程。可以使用 local指令 在宏定义体内创建或替换局部变量。
3. 循环变量:循环变量是由如list指令自动创建的,而且它们只在指令的开始和结束标记内有效。宏的参数是局部变量而不是循环变量。
4. 全局变量:这是一个高级话题了,并且这种变量最好别用。即便它们属于不同的命名空间,全局变量也被所有模板共享,因为它们是被 import进来的, 不同于 include进来的。那么它们的可见度就像数据模型那样。全局变量通过global指令来定义。
<#include "/lib/my_test.ftl">, 那么就会在主命名空间中创建两个变量,所以用import,相当于引入hash表
/lib/my_test.ftl 如下:
<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.</p>
</#macro>
<#assign mail = "jsmith@acme.com">
aWebPage.ftl 如下:
<#import "/lib/my_test.ftl" as my> <#-- the hash called "my" will be the "gate" -->
<@my.copyright date="1999-2002"/>
${my.mail}
输出:
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.</p>
修改 /lib/my_test.ftl 如下:
<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.</p>
<br>Email: ${mail}</p>
</#macro>
<#assign mail = "jsmith@acme.com">
修改 aWebPage.ftl 如下:
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
输出;
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com
主页面向其他页面赋值。<#assign mail="jsmith@other.com" in my>
private static final Configuration configuration;
static {
configuration = new Configuration(Configuration.VERSION_2_3_23);
configuration.setClassForTemplateLoading(FreeMarkerUtils.class, "/templates/");
}
public static String processAsString(String templateFileName, Object dataModel) throws IOException, TemplateException {
StringWriter writer = new StringWriter();
Template template = configuration.getTemplate(templateFileName);
template.process(dataModel, writer); //将ftl与模型产生的结果写入writer
return writer.toString();
}
## 自定义函数:
public class IndexOfMethod implements TemplateMethodModel {
public TemplateModel exec(List args) throws TemplateModelException {
if (args.size() != 2) {
throw new TemplateModelException("Wrong arguments");
}
return new SimpleNumber(
((String) args.get(1)).indexOf((String) args.get(0)));
}
}
root.put("indexOf", new IndexOfMethod());
<#assign x = "something">
${indexOf("met", x)} //2
${indexOf("foo", x)} //-1
## 内联函数
abs
x?abs ,如果 x 是 -5,会得到5
ancestors
一个包含所有结点祖先结点的序列,以直接父结点开始,以根结点结束。 该内建函数的结果也是一个方法,你可以用它和元素的 完全限定名 来过滤结果。 比如以名称 section 用 node?ancestors("section") 来获得所有祖先结点的序列
api
api_builtin_enabled 配置设置项必须设置为 true,并且值本身要支持它
1.对象包装器是 DefaultObjectWrapper,incompatibleImprovements 设置为 2.3.22 或更高
2.当被纯 BeansWrapper 包装时
3.实现了 freemarker.template.TemplateModelWithAPISupport 接口
value?api 提供访问 value 的API
如 value?api.someJavaMethod()
users 由 List 变为数组,那么 users?size 继续有效,而 users?api.size() 就会失败
boolean
字符串转为布尔值。字符串必须是 true 或 false 或者必须是由 boolean_format 设置的特定格式
byte, double, float, int, long, short
强转类型
c (当被用作是数字值时)
将 "计算机语言" 的数字转换成字符串
cap_first
字符串中的首单词的首字母大写
capitalize
字符串中所有单词的首字母大写
ceiling
返回数字小数进位后的整数 (也就是向正无穷进位)
children
chop_linebreak
在末尾没有 换行符 的字符串, 那么可以换行,否则不改变字符串
chunk
contains
counter
date for dates, for strings
需要一个由 date_format, time_format 和 datetime_format 设置指定的格式
date_if_unknown
datetime for dates, for strings
需要一个由 date_format, time_format 和 datetime_format 设置指定的格式
datetime_if_unknown
double
ends_with
ensure_ends_with
如果字符串没有以第一个参数指定的子串结尾, 那么就会将它加到字符串后面
ensure_starts_with
如果字符串没有以第一个参数指定的子串开头, 那么就会将它加到字符串前
如果指定两个参数,那么第一个参数就被解释成Java正则表达式
eval
first
floor
返回数字的舍掉小数后的整数 (也就是向负无穷舍弃)
groups
这个函数只作用于内建函数 matches 的结果
float
has_api
has_content
has_next
html
index
index_of
int
interpret
item_cycle
item_parity
item_parity_cap
is_even_item
is_first
is_infinite
辨别数字是否是无限浮点数 返回true or false
is_last
is_nan
辨别数字是否是浮点数NaN(非数) 返回true or false
is_odd_item
is_type
iso, iso_...
j_string
join
js_string
keep_after
keep_after_last
keep_before
keep_before_last
keys
last
last_index_of
left_pad
length
long
lower_abc
将 1, 2, 3,等...,转换为字符串 "a", "b", "c",等... 当到达 "z"时
那么会继续转换成如 "aa", "ab"
lower_case
matches
namespace
new
node_namespace
node_name
node_type
number
number_to_date, number_to_datetime, number_to_time
parent
replace
remove_beginning
remove_ending
reverse
right_pad
round
返回最近的整数。 如果数字以.5结尾,那么它将进位(也就是向正无穷方向进位)
root
rtf
short
size
sort
seq_contains
seq_index_of
seq_last_index_of
sort_by
split
starts_with
string: for strings, for numbers, for booleans, for date/time/date-time
<#assign x=42>
${x} 42
${x?string} <#-- the same as ${x} --> 42
${x?string.number} 42
${x?string.currency} $42.00
${x?string.percent} 4,200%
${x?string.computer} 42
//可以用<#setting number_format="currency">设置默认格式
//
<#assign x = 1.234>
${x?string["0"]} 1
${x?string["0.#"]} 1.2
${x?string["0.##"]} 1.23
${x?string["0.###"]} 1.234
${x?string["0.####"]} 1.234
${1?string["000.00"]} 001.00
${12.1?string["000.00"]} 012.10
${123.456?string["000.00"]} 123.46
${1.2?string["0"]} 1
${1.8?string["0"]} 2
${1.5?string["0"]} <-- 1.5, rounded towards even neighbor 2
${2.5?string["0"]} <-- 2.5, rounded towards even neighbor 2
${12345?string["0.##E0"]} 1.23E4
substring (deprecated)
switch
then
time for date/time/date-time, for strings
需要一个由 date_format, time_format 和 datetime_format 设置指定的格式
time_if_unknown
trim
uncap_first
upper_abc
转换成大写字母
upper_case
url
values
word_list
xhtml
xml