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码对应的字符.