一、freemarker常用指令

1 if指令

这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:


<#if condition>...

    <#elseif condition>...

    <#elseif condition>...

    <#else> ...

</#if>


例子如下:


<#assign age=23>

<#if (age>60)>老年人

    <#elseif (age>40)>中年人

    <#elseif (age>20)>青年人

    <#else> 少年人

</#if>

输出结果是:


青年人


4.2 switch , case , default , break指令

这些指令显然是分支指令,作用类似于Java的switch语句,switch指令的语法结构如下:


<#switch value>

    <#case refValue>...<#break>

    <#case refValue>...<#break>

    <#default>...

</#switch>


4.3 list, break指令

list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:


<#list sequence as item>

...

</#list>

上面的语法格式中,sequence就是一个集合对象,也可以是一个表达式,但该表达式将返回一个集合对象,而item是一个任意的名字,就是被迭代输出的集合元素.此外,迭代集合对象时,还包含两个特殊的循环变量:
item_index:当前变量的索引值
item_has_next:是否存在下一个对象
也可以使用<#break>指令跳出迭代

例子如下:


<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>

    ${x_index + 1}.${x}<#if x_has_next>,</if>

    <#if x="星期四"><#break></#if>

</#list>


4.4 include指令

include指令的作用类似于JSP的包含指令,用于包含指定页.include指令的语法格式如下:


<#include filename [options]>

在上面的语法格式中,两个参数的解释如下:
filename:该参数指定被包含的模板文件
options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,

    其中encoding指定包含页面时所用的解码集,而parse指定被包含文件是否作为FTL文件来解析,如果省略了parse选项值,则该选项默认是true.

4.5 import指令

该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import指令的语法格式如下:


<#import "/lib/common.ftl" as com>

上面的代码将导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中.

4.6 noparse指令

noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:
<#noparse>...</#noparse>

看如下的例子:


<#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>


4.7 escape , noescape指令

escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:


<#escape identifier as expression>...

 <#noescape>...</#noescape>

</#escape>


看如下的代码:


<#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的规则,如下例子:


<#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表达式.

4.8 assign指令

assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,

assign指令的用法有多种,包含创建或替换一个顶层变量,或者创建或替换多个变量等,

它的最简单的语法如下:<#assign name=value [in namespacehash]>,

这个用法用于指定一个名为name的变量,该变量的值为value,


此外,FreeMarker允许在使用assign指令里增加in子句,in子句用于将创建的name变量放入namespacehash命名空间中.

assign指令还有如下用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>,这个语法可以同时创建或替换多个顶层变量,此外,还有一种复杂的用法,如果需要创建或替换的变量值是一个复杂的表达式,则可以使用如下语法格式:<#assign name [in namespacehash]>capture this</#assign>,在这个语法中,是指将assign指令的内容赋值给name变量.如下例子:


<#assign x>

<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>

    ${n}

</#list>

</#assign>

${x}

上面的代码将产生如下输出:


星期一 星期二 星期三 星期四 星期五 星期六 星期天


虽然assign指定了这种复杂变量值的用法,但是我们也不要滥用这种用法,如下例子:<#assign x>Hello ${user}!</#assign>,以上代码改为如下写法更合适:<#assign x="Hello ${user}!">

4.9 setting指令

该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:
locale:该选项指定该模板所用的国家/语言选项
number_format:指定格式化输出数字的格式
boolean_format:指定两个布尔值的语法格式,默认值是true,false
date_format,time_format,datetime_format:指定格式化输出日期的格式
time_zone:设置格式化输出日期时所使用的时区

4.10 macro , nested , return指令

macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:


<#macro name param1 param2 ... paramN>

...

<#nested loopvar1, loopvar2, ..., loopvarN>

...

<#return>

...

</#macro>

在上面的格式片段中,包含了如下几个部分:
name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数
paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值
nested指令:nested标签输出使用自定义指令时的中间部分
nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板
return指令:该指令可用于随时结束该自定义指令.

看如下的例子:


<#macro book>   //定义一个自定义指令

j2ee

</#macro>

<@book />    //使用刚才定义的指令

上面的代码输出结果为:j2ee

在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:


<#macro book booklist>     //定义一个自定义指令booklist是参数

<#list booklist as book>

   ${book}

</#list>

</#macro>

<@book booklist=["spring","j2ee"] />   //使用刚刚定义的指令

上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:spring j2ee

不仅如此,还可以在自定义指令时使用nested指令来输出自定义指令的中间部分,看如下例子:


<#macro page title>

<html>

<head>

   <title>FreeMarker示例页面 - ${title?html}</title>

</head>

<body>

   <h1>${title?html}</h1>

   <#nested>      //用于引入用户自定义指令的标签体

</body>

</html>

</#macro>

上面的代码将一个HTML页面模板定义成一个page指令,则可以在其他页面中如此page指令:


<#import "/common.ftl" as com>     //假设上面的模板页面名为common.ftl,导入页面

<@com.page title="book list">

<u1>

    <li>spring</li>

    <li>j2ee</li>

</ul>

</@com.page>


从上面的例子可以看出,使用macro和nested指令可以非常容易地实现页面装饰效果,此外,还可以在使用nested指令时,指定一个或多个循环变量,看如下代码:


<#macro book>

    <#nested 1>      //使用book指令时指定了一个循环变量值

    <#nested 2>

</#macro>

<@book ;x> ${x} .图书</@book>

当使用nested指令传入变量值时,在使用该自定义指令时,就需要使用一个占位符(如book指令后的;x).上面的代码输出文本如下:


1 .图书    2 .图书

在nested指令中使用循环变量时,可以使用多个循环变量,看如下代码:


<#macro repeat count>

<#list 1..count as x>     //使用nested指令时指定了三个循环变量

   <#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;


return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容,看如下代码:


<#macro book>

spring

<#return>

j2ee

</#macro>

<@book />

上面的代码输出:spring,而j2ee位于return指令之后,不会输出.