FreeMarker的常用指令(二)
6、noparse指令
noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:
<#noparse>...</#noparse>
看如下的例子:
<#noparse>
<#listbooksasbook>
<tr><td>${book.name}<td>作者:${book.author}
</#list>
</#noparse>
输出如下:
<#listbooksasbook>
<tr><td>${book.name}<td>作者:${book.author}
</#list>
7、escape,noescape指令
escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:
<#escapeidentifierasexpression>...
<#noescape>...</#noescape>
</#escape>
看如下的代码:
<#escapexasx?html>
Firstname:${firstName}
Lastname:${lastName}
Maidenname:${maidenName}
</#escape>
上面的代码等同于:
Firstname:${firstName?html}
Lastname:${lastName?html}
Maidenname:${maidenName?html}
escape指令在解析模板时起作用而不是在运行时起作用,除此之外,escape指令也嵌套使用,子escape继承父escape的规则,如下例子:
<#escapexasx?html>
CustomerName:${customerName}
Itemstoship;
<#escapexasitemCodeToNameMap[x]>
${itemCode1}
${itemCode2}
${itemCode3}
${itemCode4}
</#escape>
</#escape>
上面的代码类似于:
CustomerName:${customerName?html}
Itemstoship;
${itemCodeToNameMap[itemCode1]?html}
${itemCodeToNameMap[itemCode2]?html}
${itemCodeToNameMap[itemCode3]?html}
${itemCodeToNameMap[itemCode4]?html}
对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape指令中的插值将不会添加escape表达式.
8、assign指令
assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign指令的用法有多种,包含创建或替换一个顶层变量,或者创建或替换多个变量等,它的最简单的语法如下:<#assignname=value[innamespacehash]>,这个用法用于指定一个名为name的变量,该变量的值为value,此外,FreeMarker允许在使用assign指令里增加in子句,in子句用于将创建的name变量放入namespacehash命名空间中.
assign指令还有如下用法:<#assignname1=value1name2=value2...nameN=valueN[innamespacehash]>,这个语法可以同时创建或替换多个顶层变量,此外,还有一种复杂的用法,如果需要创建或替换的变量值是一个复杂的表达式,则可以使用如下语法格式:<#assignname[innamespacehash]>capturethis</#assign>,在这个语法中,是指将assign指令的内容赋值给name变量.如下例子:
<#assignx>
<#list["星期一","星期二","星期三","星期四","星期五","星期六","星期天"]asn>
${n}
</#list>
</#assign>
${x}
上面的代码将产生如下输出:星期一星期二星期三星期四星期五星期六星期天
虽然assign指定了这种复杂变量值的用法,但是我们也不要滥用这种用法,如下例子:<#assignx>Hello${user}!</#assign>,以上代码改为如下写法更合适:<#assignx="Hello${user}!">
9、setting指令
该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#settingname=value>,在这个格式中,name的取值范围包含如下几个:
locale:该选项指定该模板所用的国家/语言选项
number_format:指定格式化输出数字的格式
boolean_format:指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format:指定格式化输出日期的格式
time_zone:设置格式化输出日期时所使用的时区
10、macro,nested,return指令
macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:
<#macronameparam1param2...paramN>
...
<#nestedloopvar1,loopvar2,...,loopvarN>
...
<#return>
...
</#macro>
在上面的格式片段中,包含了如下几个部分:
name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
nested指令:nested标签输出使用自定义指令时的中间部分
nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板
return指令:该指令可用于随时结束该自定义指令.
看如下的例子:
<#macrobook>//定义一个自定义指令
j2ee
</#macro>
<@book/>//使用刚才定义的指令
上面的代码输出结果为:j2ee
在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:
<#macrobookbooklist>//定义一个自定义指令booklist是参数
<#listbooklistasbook>
${book}
</#list>
</#macro>
<@bookbooklist=["spring","j2ee"]/>//使用刚刚定义的指令
上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:springj2ee
不仅如此,还可以在自定义指令时使用nested指令来输出自定义指令的中间部分,看如下例子:
<#macropagetitle>
<html>
<head>
<title>FreeMarker示例页面-${title?html}</title>
</head>
<body>
<h1>${title?html}</h1>
<#nested>//用于引入用户自定义指令的标签体
</body>
</html>
</#macro>
上面的代码将一个HTML页面模板定义成一个page指令,则可以在其他页面中如此page指令:
<#import"/common.ftl"ascom>//假设上面的模板页面名为common.ftl,导入页面
<@com.pagetitle="booklist">
<u1>
<li>spring</li>
<li>j2ee</li>
</ul>
</@com.page>
从上面的例子可以看出,使用macro和nested指令可以非常容易地实现页面装饰效果,此外,还可以在使用nested指令时,指定一个或多个循环变量,看如下代码:
<#macrobook>
<#nested1>//使用book指令时指定了一个循环变量值
<#nested2>
</#macro>
<@book;x>${x}.图书</@book>
当使用nested指令传入变量值时,在使用该自定义指令时,就需要使用一个占位符(如book指令后的;x).上面的代码输出文本如下:
1.图书2.图书
在nested指令中使用循环变量时,可以使用多个循环变量,看如下代码:
<#macrorepeatcount>
<#list1..countasx>//使用nested指令时指定了三个循环变量
<#nestedx,x/2,x==count>
</#list>
</#macro>
<@repeatcount=4;chalfclast>
${c}.${halfc}<#iflast>Last!</#if>
</@repeat>
上面的输出结果为:
1.0.52.13.1.54.2Last;
return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容,看如下代码:
<#macrobook>
spring
<#return>
j2ee
</#macro>
<@book/>
上面的代码输出:spring,而j2ee位于return指令之后,不会输出.
用户定义指令
l宏和变换器变量是两种不同类型的用户定义指令,它们之间的区别是宏是在模板中使用macro指令定义,而变换器是在模板外由程序定义,这里只介绍宏
l基本用法
Ø宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子:
<#macrogreet>
<fontsize="+2">HelloJoe!</font>
</#macro>
Ø作为用户定义指令使用宏变量时,使用@替代FTL标记中的#
<@greet></@greet>
Ø如果没有体内容,也可以使用:
<@greet/>
l参数
Ø在macro指令中可以在宏变量之后定义参数,如:
<#macrogreetperson>
<fontsize="+2">Hello${person}!</font>
</#macro>
Ø可以这样使用这个宏变量:
<@greetperson="Fred"/>and<@greetperson="Batman"/>
输出结果是:
<fontsize="+2">HelloFred!</font>
and<fontsize="+2">HelloBatman!</font>
Ø宏的参数是FTL表达式,所以下面的代码具有不同的意思:
<@greetperson=Fred/>
Ø这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式
Ø宏可以有多参数,下面是一个例子:
<#macrogreetpersoncolor>
<fontsize="+2"color="${color}">Hello${person}!</font>
</#macro>
Ø可以这样使用该宏变量:
<@greetperson="Fred"color="black"/>
Ø其中参数的次序是无关的,因此下面是等价的:
<@greetcolor="black"person="Fred"/>
Ø只能使用在macro指令中定义的参数,并且对所有参数赋值,所以下面的代码是错误的:
<@greetperson="Fred"color="black"background="green"/>
<@greetperson="Fred"/>
Ø可以在定义参数时指定缺省值,如:
<#macrogreetpersoncolor="black">
<fontsize="+2"color="${color}">Hello${person}!</font>
</#macro>
Ø这样<@greetperson="Fred"/>就正确了
Ø宏的参数是局部变量,只能在宏定义中有效
l嵌套内容
Ø用户定义指令可以有嵌套内容,使用<#nested>指令执行指令开始和结束标记之间的模板片断
Ø例子:
<#macroborder>
<tableborder=4cellspacing=0cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
这样使用该宏变量:
<@border>Theborderedtext</@border>
输出结果:
<tableborder=4cellspacing=0cellpadding=4><tr><td>
Theborderedtext
</tr></td></table>
Ø<#nested>指令可以被多次调用,例如:
<#macrodo_thrice>
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>
输出结果:
Anything.
Anything.
Anything.
Ø嵌套内容可以是有效的FTL,下面是一个有些复杂的例子:
<@border>
<ul>
<@do_thrice>
<li><@greetperson="Joe"/>
</@do_thrice>
</ul>
</@border>
输出结果:
<tableborder=4cellspacing=0cellpadding=4><tr><td>
<ul>
<li><fontsize="+2">HelloJoe!</font>
<li><fontsize="+2">HelloJoe!</font>
<li><fontsize="+2">HelloJoe!</font>
</ul>
</tr></td></table>
Ø宏定义中的局部变量对嵌套内容是不可见的,例如:
<#macrorepeatcount>
<#localy="test">
<#list1..countasx>
${y}${count}/${x}:<#nested>
</#list>
</#macro>
<@repeatcount=3>${y?default("?")}${x?default("?")}${count?default("?")}</@repeat>
输出结果:
test3/1:???
test3/2:???
test3/3:???
Ø
l在宏定义中使用循环变量
Ø用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在<@…>开始标记的参数后面指定循环变量的名字
Ø例子:
<#macrorepeatcount>
<#list1..countasx>
<#nestedx,x/2,x==count>
</#list>
</#macro>
<@repeatcount=4;c,halfc,last>
${c}.${halfc}<#iflast>Last!</#if>
</@repeat>
输出结果:
1.0.5
2.1
3.1.5
4.2Last!
Ø指定的循环变量的数目和用户定义指令开始标记指定的不同不会有问题
n调用时少指定循环变量,则多指定的值不可见
n调用时多指定循环变量,多余的循环变量不会被创建