Freemarker(ftl)

Freemarker是什么

  • FreeMarker是模版引擎:是一种基于模版和要改变的数据,并用来生成(HTML页面、邮件、配置文件、源代码等)的通用工具。

用Freemarker的理由

1、性能。velocity应该是最好的,其次是jsp,普通的页面freemarker性能最差(虽然只是几毫秒到十几毫秒的差距)。但是在复杂页面上(包含大量判断、日期金额格式化)的页面上,freemarker的性能比使用tag和el的jsp好。
2、宏定义比jsp tag方便
3、内置大量常用功能。比如html过滤,日期金额格式化等等,使用非常方便
4、支持jsp标签
5、可以实现严格的mvc分离


Freemarker规则整理

FreeMarker模版文件主要有4部分组成:

  • 文本:直接输出的部分;
  • 插值:${} #{} 格式的部分,将使用数据模型中的部分替代输出;
  • FTL指令:FreeMarker指定的和HTML标记类似的标签,名字前加# 用来区分,不输出;
  • 注释:<#--此处为注释文本-->,不输出;
<html>
    <head>
        <title>welcome to FreeMarker</title>
    </head>
    <body>
        <#--此处为注释-->
        <#-- 下面为插值 -->
        <h2>Welcome ${user} !</h2>
        <#-- 下面为FTL指令 -->
        <#list>
            <li>${sth.name} for ${sth.price}</li>
        </list>
    </body>
</html>

插值规则

FreeMarker的差值有两种类型:

  • 通用插值${expr}
  • 数字格式化插值 #{expr}#{expr;format}

基本输出:

  • 输出 ${user.name}
  • 空值判断
${user.name?if_exists}
${user.name?default('xxx')}
${user.name!"xxx"} 默认值xxx
  • 日期格式 ${user.name?string('yyyy-MM-dd')}
  • 数字格式
${age?string.number}  //20
${age?string.currency}  //$20.00
${age?string.percent}  //20%

FTL指令规则

在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,与HTML类似:

  • 开始标签 <#directName param>
  • 结束标签 </#directName>
  • 空标签 <#directName param />

遍历List集合

<#-- 逐个输出list中的元素:a b c d -->
<#list ['a','b','c','d'] as item>
    ${itam}
</#list>

迭代集合对象时,还包含两个特殊的循环便量:item_index当前变量的索引值;item_has_next是否存在下一个对象;也可以使用<#break>指令跳出迭代。

遍历map集合

{"liu":100, "sun":120}
<#list map ? keys as key>
    ${key}=${map[key]}
</#list>

逻辑判断

  • if判断
<#if condition1>
<#elseif condition2>
...
<#else>
</#if>
  • switch判断
<#switch value>
    <#case refValue>
        <#break>
    <#case refValue2>
        <#break>
    <#default>
</#switch>

内置函数

常用的内置的字符串函数:

  • html对字符串进行HTML编码
  • cap_first使字符串第一个字母大写
  • lower_case将字符串转换为小写
  • upper_case将字符串转换为大写
  • trim去掉字符串前后的空白字符

常用的内置的集合的函数

  • size获取序列中元素的个数
  • chunk分成几个一组
  • xxx_index计数器

常用的内置的数字值的函数

  • int获得数字的整数部分,带符号

空值处理

  • FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同
  • 为了处理缺失变量,FreeMarker提供了两个运算符:
    • ! 指定缺失变量的默认值
    • ?? 判断某个变量是否存在
    • 其中! 运算符的用法有两种:variable! variable!defaultValue,第一种用法不给缺失的变量指定默认值,表明默认值是空字符串,长度为0的集合,或者长度为0的Map对象;
    • 使用! 指定默认值时,并不要求默认值的类型和变量类型相同。使用??运算符总是返回一个布尔值,用法为variable?? 如果该变量存在则返回true,否则返回false。

变量的声明

  • plain变量 :可以在模版的任何地方访问,包括使用 include 指令插入的模版,使用 assign 指令创建和替换
<#assign num=0 />
<#assign x="Hello ${user}!">
  • 局部变量:在宏定义体中有效,使用local指令创建和替换;注意:宏的参数是局部变量,不是循环变量;
  • 循环变量:只能存在于指令的嵌套内容,由指令(如list指令)自动创建;

运算符的优先级

FreeMarker中运算符的优先级如下(高–>低)

  • 一元运算符 !
  • 内建函数 ?
  • 乘除法 * / %
  • 加减法 + -
  • 比较 > < >= <= lt lte gt gte
  • 相等 == = !=
  • 逻辑与 &&
  • 逻辑或 ||
  • 数字范围 ...

其他指令

include指令

  • include指令:包含作用;用于包含指定页。
  • <#include filename [options]>
  • filename:该参数指定被包含的模版文件
  • options:该参数可以省略,指定包含时的选项,包含encodingparse两个选项,其中encoding指定了包含页面时所用的解码集,parse指定被包含文件是否作为FTL文件来解析,默认true。

import指令

  • import指令:该指令用于导入FreeMarker模版中的所有变量,并将该变量放置在指定的Map对象中。
  • <#import "/lib/common.ftl" as com>
  • 上述代码将导入 /lib/common.ftl 模版文件中的所有变量,将这些变量放在一个名为com的map对象中

setting指令

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

macro nested return 指令

  • macro指令:用于实现自定义指令,通过使用自定义指令,可以将一段模版片段定义为一个用户指令
<#macro name param1 param2 param3>
...
<#nested loopvar1, loopvar2, loopvar3>
...
<#return>
</#macro>
  • 上述指令中:
  • name 属性指定该自定义指令的名字,使用自定义指令时可以传入多个参数
  • param 该指令是使用自定义指令时的参数,使用时必须为参数传入值
  • nested指令:输出使用自定义指令时的中间部分
  • return指令:可用于随时结束该自定义指令

宏是什么

  • 宏是在模版中使用macro指令定义
  • 宏是和某个变量关联的模版片段,以便在模版中通过用户定义指令使用该变量

为什么使用宏

宏的用法

注意点:调用宏时,与使用FreeMarker的其他指令类似,只是使用@ 替代FTL标记中的#

macro 定义模版,然后调用直接显示

<#macro greet>
    <font size="+3">Hello macro!</font>
</#macro>

<@greet></@greet>

结果:<font size="+3">Hello macro!</font>

macro 指令中可以在宏变量之后定义参数

<#macro greet person>
    <font size="+3">Hello ${person}!</font>
</#macro>

<@greet person="Fred" />

结果:<font size="+3">Hello Fred!</font>

macro 定义多个参数

<#macro greet person color="black">
    <font size="+3" color="${color}">Hello ${person}!</font>
</#macro>

自定义指令嵌套内容<#nested>

<#macro border>
    <table border=4 cellspacign=0 cellpadding=4>
        <tr><td><#nested></td></tr>
    </table>
</#macro>

<@border>The border text</@border>

结果:

    <table border=4 cellspacign=0 cellpadding=4>
        <tr><td>The border text</td></tr>
    </table>

记住:<#nested> 就相当于占位符
<#nested> 指令可以被多次调用

<#macro do_thrice>
    <#nested>
    <#nested>
    <#nested>
</#macro>

<@do_thrice>Some text

结果:Some text Some text Some text

局部变量对嵌套内容不可见

<#macro repeat count>
    <#local y="test">
        <#list 1...count as x>
            ${y} ${count}/${x}: <#nested>
        </#list>
</#macro>

<@repeat count=3>${y?default("?")}${x?default("?")}${count?default("?")}</@repeat>

结果:

test 3/1:???
test 3/2:???
test 3/3:???

宏定义中使用循环变量

  • nested指令也可以有循环变量,调用宏的时候在宏指令的参数后面,分号隔开依次列出循环变量的名字
  • <@ macro_name param_list; loop_variable_list>
<#macro repeat count>
    <#list 1..count as x>
        <#nested x, x/2, x==count>
    </#list>
</#macro>


<@repeat count=4; c, half, last>
    ${c}.${halfc}<#if last>Last!</#if>
</@repeat>

其中,count是宏的参数,c, half, last 是循环变量
结果:

10.5
2 1
3 1.5
4 2 Last!

循环变量和宏标记指定的不同不会有问题,若调用时少指定了循环变量,那么多余的值不可见;若调用时多指定了循环变量,多余的循环变量不会被创建。


猜你喜欢

转载自blog.csdn.net/sunxiaofre/article/details/78232068
今日推荐