FreeMarker梳理
组成: 1.文本:直接输出的部分
2.注释:<#-- ... -->
3.值:即${...}、#{...}
4.FTL指令: 开始标签 <#directivename parameter> 结束标签 </#directivename>
空标签 <#directivename parameter/>
Ps.< 、/> 和指令之间不允许有空白字符
Eg 1.
<ul>
<#list animals as dog>
<li>${dog.name}</li>
</#list>
</ul>
变量:1.分别是数据模型的变量【页面放在map中传入的变量】
<#assign>定义的变量】
Ps.若模板变量和模型变量名称一致,不是覆盖,而是模型变量被隐藏
可以使用.globals可以访问模型变量
Eg 2.<#assign username="李四">
${username} 输出:李四
${.globals.username} 输出:张三
Assign指令:创建或替换一个顶层变量,创建或替换多个变量
a.<#assign name=value [in namespacehash]>
b.<#assign name1=value1 name2=value2 .. nameN=valueN [in namespacehash]>
c.<#assign name [in namespacehash]>capture this</#assign>(不建议)
声明】
Ps.调用该指令后,模板变量被覆盖,该方式存在风险,一般不使用
Eg 3.<#macro test>
<#local username="王五"/>
</#macro>
<@test/>
4.循环变量【在循环中的变量】
Ps.在list循环中定义的变量,只在循环中有效,一种临时的变量定义方式
Eg 1.中${dog}即为循环变量
数字格式化:
1.使用内建函数
不管其表现形式是怎样的(例 如"123,456.123,456"、"123456.123456"、"000123456.123456000"、"123,456.123456"、"1,2345,6.123456"), 只要小数分割符是'.'它就能转化成计算机能够识别的字符串形式,${str?c}
Eg. ${"123,456.123,456"?c} 输出123456.123456
2.预定义数字格式
有四种预定义的数字格式,分别是computer(跟内建函数c功能一样,用法不一样)、currency(货币格式)、number(数字格式)、percent(百分比形式)
Ps.这些格式的明确含义是本地化(国家)指定的,受Java平台安装环境所控制,而不是FreeMarker,所以不建议用这些函数,而且受默认数字格式的影响,用法不灵活3.类似java数字格式语法
"0.#",左边的0的个数代表整数部分最少为多少位,右边#的个数代表小数部分最多为多少位;strnum是一个数字,${strnum?string(",##0.0#")}
Eg. ",##0.0#" 整数部分的千位分割符是',' 小数部分最多两位 最少一位;
"0.##%"以百分比的形式表示,小数部分最多两位。
${123456.123456?string(",##0.0#")}值为123,456.124.局部设置
用到的数字格式化是相同的,可考虑统一配置数字的格式化形式,只需在用到需要格式化的数字之前设置<#setting number_format=",##0.##">
Ps.若用在一个页面,则整个页面默认该格式,除非用string函数覆盖了默认的格式,同样的,如果放在一个公共的页面,其它页面只要include它,也会是同样的格式。5.全局设置
所有的页面都默认提供数字的格式化形式
(针对spring):在freemarker的配置文件中设置其默认的数字格式化形式,如下:
<property name="freemarkerSettings">
<props>
.....
<prop key="number_format">0.##</prop>
......
</props>
</property> 6.舍入处理
round,floor,ceiling 和string("0")
strnum是一个数字,${strnum?round(floor/ceiling)}
${strmun?string("0")}
Eg. 1.5?string("0") 输出 2
2.5?string("0") 输出 2
Ps.对最近的“邻居”进行四舍五入,离两个邻居距离相等,四舍五入到偶数的邻居。String函数中数字格式语法可用 在解析数据格式的时候,freemarker自动默认将数字按3为分割(1,000),解决方法有如下几种:
a.在模板中直接加.toString()转化数字为字符串,
${num.toString()}; b.在freemarker配置文件freemarker.properties或模板中加
<#setting number_format="#">或者 <#setting number_format="0">; Eg.<#if AdminLanguagePaginationMsg?exists>
<#setting number_format="#"> Ps.数字格式化的优先级: string优先级最高,配置文件配置的优先级最低,在页面setting的优先级在两者之间。
插值:
1.通用插值${expr}
a.插值结果为字符串值:直接输出表达式结果
b.插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值 Ps.预订义三种数字格式:number,currency(货币)和percent(百分比)其中number 为默认的数字格式转换
Eg.<#setting number_format="currency"/>
<#assign answer=42/>
${answer} 输出$42.00
${answer?string}输出$42.00
${answer?string.number} 输出42.00
${answer?string.currency} 输出$42.00
${answer?string.percent} 输出4200% c.插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值
Eg.${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}
输出2008-04-08 08:08:08 Pacific Daylight Time
${lastUpdated?string("EEE, MMM d, yy")} 输出Tue, Apr 8, 03
${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}输出Tuesday, April 08, 2003, 08:08:08 PM (PDT)
d.插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值
Eg.<#assign foo=true/>
${foo?string("yes", "no")} 输出结果是: yes
2.数字格式化插值:#{expr}或#{expr;format}
Ps.format可以是: mX:小数部分最小X位; MX:小数部分最大X位
Eg.<#assign x=2.582/>
<#assign y=4/>
#{x; M2} <#-- 输出2.58 -->
#{y; M2} <#-- 输出4 -->
#{x; m1} <#-- 输出2.6 -->
#{y; m1} <#-- 输出4.0 -->
#{x; m1M2} <#-- 输出2.58 -->
#{x; m1M2} <#-- 输出4.0 -->
表达式:
1.直接指定值
使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象.
a.字符串
直接指定字符串值使用单引号或双引号限定,字符串值中包含特殊字符需要转义
Eg.${"我的文件保存在C:\\盘"} 输出 我的文件保存在C:\盘
Ps.若某段文本中包含大量的特殊符号,可以在指定字符串内容的引号前增加r标 记,在r标记后的文件将会直接输出.${r"${foo}"}
b.数值
表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker目前还不支持科学计数法,所以"1E3"是错误的。Ps. 数值不能省略小数点前面的0,所以".5"是错误的写法
‚数值8 , +8 , 8.00都是相同的
c.布尔值
直接使用true和false,不使用引号.
d.集合
集合以方括号包括,各集合元素之间以英文逗号","分隔 Eg.<#list ["星期一", "星期二", "星期三"] as x>
${x}
</#list>
Ps.除此之外,集合元素也可以是表达式,例子如下:
[2 + 2, [1, 2, 3, 4], "whatnot"]
使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],更有效率,无需使用 方括号,数字范围也支持反递增的数字范围,如5..2
e.Map对象
Map对象使用花括号包括
Eg.{"语文":78, "数学":80}
Ps.Map对象的key和value都是表达式,但是key必须是字符串
2.输出变量值
a.顶层变量
直接使用${variableName}来输出变量值Ps.变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为
b.输出集合元素
若需要输出集合元素,week为["星期一","星期二","星期三"]
Eg. ${week[2]} 输出 星期三
${week[0..2]} 返回week集合的子集合,第0-2个元素
c.输出Map元素
${book.key}3.字符串操作
字符串连接有两种语法:
a.使用${..}或#{..}在字符串常量部分插入表达式的值b.直接使用连接运算符+来连接字符串
Eg. ${"hello, ${user}!"} 输出 hello,annlee!
${"hello, " + user + "!"} 输出 hello,annlee!
Ps.${..}只能用于文本部分,不能用于表达式,下面的代码是错误的:
<#if ${isBig}>Wow!</#if>
<#if "${isBig}">Wow!</#if>
应该写成:<#if isBig>Wow!</#if>
“+”可直接将两个集合或者map进行拼接
截取子串可以根据字符串的索引来进行:
Eg. ${book[0]}${book[4]} //结果是su
${book[1..4]} //结果是tru4.算数运算
a.使用内建的int函数可对数值取整${num?int}
b.使用+,一边是数字,一边是字符串,自动将数字转为字符串再连接
c.运算符两边的运算数字必须是数字
5.比较运算符
a.=或者==:判断两个值是否相等.b.!=:判断两个值是否不等.
c. >或者gt:判断左边值是否大于右边值
d.>=或者gte:判断左边值是否大于等于右边值
e.<或者lt:判断左边值是否小于右边值
f.<=或者lte:判断左边值是否小于等于右边值
Ps. =和!=可用于字符串,数值和日期的比较,=和!=两边必须相同类型其它的运行符可用于数字和日期,不能作用于字符串
gt等字母运算符代替>会有更好的效果,FreeMarker会把>解释成FTL标签的结束字符,也可以使用括号来避免这种情况,如:<#if (x>y)>
6.逻辑运算符
逻辑与:&&
逻辑或:||
逻辑非:!
Ps.逻辑运算符只能作用于布尔值,否则将产生错误7.内建函数
任何变量后紧跟?,?后紧跟内建函数,就可通过内建函数来轮换输出变量.
var?html:对字符串进行HTML编码
var?cap_first:使字符串第一个字母大写
var?lower_case:将字符串转换成小写
var?upper_case:将字符串转换成大写 var?Length:取得字符串长度
var?trim:去掉字符串前后的空白字符 var?cap_first:首字符大写
var?uncap_first:首字符小写
var?Capitalize:每个单词的首字符大写
Sequence?size:获取序列中元素的个数
num?int:取得数字的整数部分,结果带符号 var?j_string:在字符串引号前加/
var?replace(str,restr(,‘规则参数’)):
规则参数包含: i r m s c f 具体含义如下:
i: 大小写不区分.
f: 只替换第一个出现被替换字符串的字符串
r: restr是正则表达式 var?index_of(str(,count)):指定字符在变量(第count次)位置
var?first:返回第一个值var?Last:返回最后一个值
Sequence?first:对sequence按里面的对象toString()的结果进行排序
Sequence?sort_by(value)对sequence 按里面对象的属性value排序
sequence?sort_by(name) 对sequence 按里面对象的属性name排序
Eg. <#assign test="Tom & Jerry">
${test?html} 输出Tom & Jerry
${test?upper_case?html} 输出TOM & JERRY
<#if operator?size gt 1>
<#list operator as operator></#list>
</#if>
<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";
输出: String BEAN_NAME = "The \"foo\" bean.";
8.空值处理运算符
a.!:指定缺失变量的默认值,variable!、variable!defaultValue,不给 缺失变量指定默认值,默认值是空串、长度为0的集合,长度为0的 Map对象.
b.??:判断某个变量是否存在,返回一个布尔值,该变量存在true,否则false
Eg. ${product.color!"red"}
${xxx?if_exists} 输出布尔形
${xxx??} 输出布尔形
<#if mouse?exists></#if>c.在类路径下加入 freemarker.properties 文件,里面配置
classic_compatible=true
d.通过freemarker.template.Configuration的
config.setClassicCompatible(true)
f.在ftl文件内引入
<!--#setting classic_compatible=true-->
9.运算符的优先级
FreeMarker中的运算符优先级如下(由高到低排列):
a.一元运算符:!
b.内建函数:?
c.乘除法:*, / , %
e.加减法:- , +
f.比较:> , < , >= , <= (lt , lte , gt , gte)
g.相等:== , = , !=
h.逻辑与:&&
i.逻辑或:||
j.数字范围:.. Ps.使用括号来严格区分,可读性好
常用指令 (按使用频率由高到低排序)
1 if指令
<#if condition>...
<#elseif condition>...
<#elseif condition>...
<#else> ...
</#if>2.switch , case , default , break指令
<#switch value>
<#case refValue>...<#break>
<#case refValue>...<#break>
<#default>...
</#switch>3.list, break指令
<#list sequence as item>
... <#if x="XXX"><#break></#if>
</#list> 4.include指令
include指令的作用类似于JSP的包含指令,用于包含指定页.<#include filename [options]>
options包含两个属性
a.encoding=”GBK” 编码格式
b.parse=true 是否作为ftl语法解析,默认true,false以文本方 式引入.Eg.<#include "head_bus_route.ftl"/>
Ps.可将所有的css,js文件放入filename 中
5.import指令
该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import指令的语法格式如下:
<#import "/lib/common.ftl" as com>
导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中。6.noparse指令
noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语 法格式如下:
<#noparse>...</#noparse>
Eg. <#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> 7.setting指令
该指令用于设置运行环境,该指令的语法格式如下:<#setting name=value>
name的取值范围包含如下几个:
locale:该选项指定该模板所用的国家/语言选项
number_format:指定格式化输出数字的格式
boolean_format:指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format:指定格式化输出日期
time_zone:设置格式化输出日期时所使用的时区
8.escape , noescape指令()
escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:
<#escape identifier as expression>...
<#noescape>...</#noescape>
</#escape>
Eg. <#escape x as x?html>
First name:${firstName}
Last name:${lastName}
Maiden name:${maidenName}
</#escape>
上面的代码等同于:
First name:${firstName?html}
Last name:${lastName?html}
Maiden name:${maidenName?html} escape指令在解析模板时起作用而不是在运行时起作用,除此之外,escape 指令也嵌套使用,子escape继承父escape的规则,如下例子:
Eg. <#escape x as x?html>
Customer Name:${customerName}
Items to ship;
<#escape x as itemCodeToNameMap[x]>
${itemCode1}
${itemCode2}
${itemCode3}
${itemCode4}
</#escape>
</#escape>
上面的代码类似于:
Customer Name:${customerName?html}
Items to ship;
${itemCodeToNameMap[itemCode1]?html}
${itemCodeToNameMap[itemCode2]?html}
${itemCodeToNameMap[itemCode3]?html}
${itemCodeToNameMap[itemCode4]?html}
对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape指令中的插值将不会添加escape表达式.9.macro, nested, return
<#macro name param1 param2 ... paramN>
...
<#nested loopvar1, loopvar2, ..., loopvarN>
...
<#return>
...
</#macro> name:指定该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX:指定使用自定义指令参数,使用该自定义指令时,必须为这些参 数传入值
nested指令:nested标签输出使用自定义指令时的中间部分
nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给 使用标签的模板
return指令:该指令可用于随时结束该自定义指令.
Eg. <#macro test foo bar="Bar" baaz=-1>
Test text, and the params: ${foo}, ${bar}, ${baaz}
</#macro>
<@test foo="a" bar="b" baaz=5*5-2/>
<@test foo="a" bar="b"/>
<@test foo="a" baaz=5*5-2/>
<@test foo="a"/>
输出
Test text, and the params: a, b, 23
Test text, and the params: a, b, -1
Test text, and the params: a, Bar, 23
Test text, and the params: a, Bar, -1
定义循环输出的宏
<#macro list title items>
<p>${title?cap_first}:
<ul>
<#list items as x>
<li>${x?cap_first}
</#list>
</ul>
</#macro>
<@list items=["mouse", "elephant", "python"] title="Animals"/>
输出结果
<p>Animals:
<ul>
<li>Mouse
<li>Elephant
<li>Python
</ul> 包含body的宏
<#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>
输出
1. 0.5
2. 1
3. 1.5
4. 2 Last!
FreeMarker转义字符:
\";双引号(u0022)
\';单引号(u0027)
\\;反斜杠(u005C)
\n;换行(u000A)
\r;回车(u000D)
\t;Tab(u0009)
\b;退格键(u0008)
\f;Form feed(u000C)
\l;<
\g;>
\a;&
\{;{
\xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.