`
zengshaotao
  • 浏览: 792028 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

FreeMarker基础

 
阅读更多

哈希表是一个容器,里面存储的是键值对。
如果仅存储单值的变量被称之为标量。
FreeMarker指令是不会直接输出东西的。这些标签的使用一般以符号#开头。用户自定义的FTL标签使用@符号来代替#。
其他任何不是FTL标签,插值或注释的内容将被视为静态文本,这些东西就不会被FreeMarker所解析,会被按照原样输出出来。
Comments注释:FreeMarker的注释和HTML的注释相似,但是它用<#--和-->来分隔。任何介于这两个分隔符(包含分隔符本身)之间内容会被FreeMarker忽略,就不会输出出来了。

<#if animals.python.price<animals.elephant.price>
  oh my god
<#else>
  that is nomal!
</#if>

当条件不满足时if指令之间的内容不再被显示。
freemarker只解析特殊的指令和标签,其他的按原样输出。
<h1>
  welcome ${user}<#if user=="zengshaotao"> our   leader</#if>
</h1>

如果变量是布尔值(true或者false),那么就可以直接让其作为if的条件condition:
<#if animals.python.protected>
Warning! Pythons are protected animals!
</#if>

当需要遍历集合的内容时,list指令是相当好用的。
list指令的一般格式为:
<#list sequence as loopVariable>repeatThis</#list>
repeatThis部分将会在给定的sequence遍历时的每项中重复,从第一项开始,一个接着一个。所有的重复中loopVariable将持有当前项的值。这个循环变量仅存在于<#list …>和</#list>标签之间。
<#list animals as animal>
<li>${animal}
</#list>

使用include指令,我们可以插入其他文件内容到当前的模板中
<#include "/copyright_footer.html">
注意包含的路径问题,是一种静态的包含。

在页面也可以多次使用指令,而且指令间可以相互嵌套,正如在HTML元素中嵌套使用标签一样。

<p>We have these animals:
<table border=1>
<tr><th>Name<th>Price
<#list animals as being>
<tr>
<td>
<#if being.size == "large"><font size="+1"></#if>
${being.name}
<#if being.size == "large"></font></#if>
<td>${being.price} Euros
</#list>
</table>

FreeMarker并不解析FTL标签外的文本,插值和注释,条件不满足时它也会忽略所有嵌套的font标签,即html标签。

通过在变量名后面跟着一个!和默认值来避免变量丢失这种情况。就${user!"oh"}从数据模型中丢失时,模板将会将user的值表现为字符串”oh”。(若user并没有丢失,那么模板就表现出”oh”不存在一样)

当然也可以通过放置??在变量名后面来询问FreeMarker一个变量是否存在.<#if user??><h1>Welcome ${user}!</h1></#if>

关于多级访问的变量,比如animals.python.price,书写代码:animals.python.price!0,仅当animals.python存在而仅仅最后一个子变量price可能不存在(这种情况下我们假设价格是0)。如果animals或者python不存在,那么模板处理将会以“未定义的变量”错误停止。为了防止这种情况的发生,可以这样来书写代码(animals.python.price)!0。这种情况下当animals或python不存在时表达式的结果仍然是0。对于??也是同样用来的处理这种逻辑的:animals.python.price??对比(animals.python.price)??

要注意一个数值也可有多种类型,对于一个数值可能存在哈希表和序列这两种类型,这时,该变量就支持索引和名称两种访问方式。不过容器基本是当作哈希表或者序列来使用的,而不是两者同时使用

一个值是方法或函数的时候那么它就可以计算其他的值,结果取决于传递给它的参数。

在数据模型中放置了一个方法变量avg,那么它就可以被用来计算数字的平均值。给定3和5作为参数,访问avg时就能得到结果4

用户自定义指令是一种子程序,一种可以复用的模板代码段

插值仅仅可以在文本中间使用(也可以在字符串表达式中)

,指令有两种类型:预定义指令和用户自定义指令。对于用户自定义的指令使用@来代替#,比如<@mydirective parameters>...</@mydirective>。更深的区别在于如果指令没有嵌套内容,那么必须这么使用<@mydirective parameters />

。如果文本本身包含用于字符引用的引号(双引号”或单引号’)或反斜杠时,应该在它们的前面再加一个反斜杠,这就是转义。转义允许你直接在文本中输入任何字符,包括反斜杠

注意字符序列${(#{)有特殊的含义,它们被用做插入表达式的数值(典型的应用是:"Hello ${user}!")。如果想要打印${,就要使用下面所说的原生字符串。
一种特殊的字符串就是原生字符串。在原生字符串中,反斜杠和${没有特殊的含义,它们被视为普通的字符。为了表明字符串是原生字符串,在开始的引号或单引号之前放置字母r,例如:
${r"${foo}"}
${r"C:\foo\bar"}
将会打印:
${foo}
C:\foo\bar

<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>

 

 

=或!=两边的表达式的结果都必须是标量,而且两个标量都必须是相同类型

可以使用lt代替<,lte代替<=,gt代替>,gte代替>=

逻辑操作符仅仅在布尔值之间有效,若用在其他类型将会产生错误导致模板执行中止

内建函数以?形式提供变量的不同形式或者其他信息。使用内建函数的语法和访问哈希表子变量的语法很像,除了使用?号代替点,其他都一样。例如得到字符串的大写形式:user?upper_case。

内建函数html: 字符串中所有的特殊HTML字符都需要用实体引用来代替(比如<代替&lt;)
${test?html}
${test?upper_case?html}
假设字符串test存储”Tom & Jerry”,那么输出为
Tom &amp; Jerry
TOM &amp; JERRY

${seasons?size}
${seasons[1]?cap_first} <#-- left side can by any expression -->
${"horse"?cap_first}
假设seasons存储了序列"winter", "spring", "summer", "autumn",那么上面的输出将会是:
4
Spring
Horse

可以使用方法调用操作来使用一个已经定义的方法。方法调用的语法形式是使用逗号来分割在括号内的表达式而形成的参数列表,这些值就是参数。方法调用操作将这些值传递给方法,然后返回一个结果,这个结果就是整个方法调用表达式的值。

为不存在的变量进行处理
${mouse!"No mouse."}
<#assign mouse="Jerry">
${mouse!"No mouse."}

:unsafe_expr??或(unsafe_expr)??
这个操作符告诉我们一个值是否存在。基于这种情况,结果是true或false。

 

 

插值表达式的结果必须是字符串,数字或日期类型的,因为只有数字和日期类型可以自动转换为字符串类型,其他类型的值(如布尔,序列)只能手动转换为字符串类型,否则就会发生错误导致模板执行中止。

若要使用插值方式来打印布尔值会引起错误,中止模板的执行。例如:${a == 2}就会引起错误,不会打印”true”或其他内容。

我们可以使用内建函数string来将布尔值转换为字符串形式。比如打印变量”married”(假设它是布尔值),那么可以这么来写: ${married?string("yes", "no")}。

自定义指令可以使用macro指令来定义.宏是有一个变量名的模板片段.

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

在<#macro greet>和</#macro>之间的内容(称为宏定义体).可以在FTL标记中通过@代替#来使用自定义指令。使用变量名作为指令名。而且,自定义指令的结束标记也是需要的。那么,就可以这样来使用greet了:<@greet></@greet>或者<@greet/>
输出的如下内容
<font size="+2">Hello Joe!</font>是给客户端浏览器的。

宏能做的还有很多,因为在<#macro ...>和</#macro>之间的东西是模板片段,也就是说它可以包含插值(${...})和FTL标签(如<#if ...>...</#if>)。

我们来改进greet宏使之可以使用任意名字,而不仅仅是”Joe”。为了实现这个目标,就要使用到参数。在macro指令中,宏名称的后面位置是用来定义变量的。这里我们仅在greet宏中定义一个变量, person:
<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>
那么就可以这样来使用这个宏:
<@greet person="Fred"/> and <@greet person="Batman"/>
这和HTML的语法是很相似的,它会打印出:
那么就看到了,宏参数的真实值是可以作为变量(person)放在宏定义体中的。使用预定义指令,参数的值(=号后边的值)可以是FTL表达式。这样,不像HTML,"Fred"和"Batman"的引号就可以不用要了。<@greet person=Fred/>也意味着使用变量的值Fred作为person参数,而不是字符串"Fred"。当然参数值并不一定是字符串类型,也可以是数字,布尔值,哈希表,序列等…也可以在=号左边使用复杂表达式(比如someParam=(price + 50)*1.25)。
自定义指令可以有多个参数。如下所示,再添加一个新参数color:
那么,这个宏就可以这样来使用:
<@greet></@greet>
<@greet/>
<font size="+2">Hello Joe!</font>
<#macro greet person>
<font size="+2">Hello ${person}!</font>
</#macro>
<@greet person="Fred"/> and <@greet person="Batman"/>
这和HTML的语法是很相似的,它会打印出:
<font size="+2">Hello Fred!</font>
and <font size="+2">Hello Batman!</font>

自定义指令可以有多个参数。如下所示,再添加一个新参数color:
<#macro greet person color>
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>
这个宏就可以这样来使用:
<@greet person="Fred" color="black"/>
参数的顺序不重要,下面这个和上面的也是相同的。
<@greet color="black" person="Fred"/>
使用时不能使用多余的参数。

使用默认宏变量的定义:
<#macro greet person color="black">
<font size="+2" color="${color}">Hello ${person}!</font>
</#macro>

我们这么使用宏就可以了:<@greet person="Fred"/>,因为它和<@greet person="Fred" color="black"/>是相同的,这样参数color的值就是已知的了。如果想给color设置为”red”,那么就写成:,这时macro指令就会使用这个值来覆盖之前设置的通用值,参数color的值就会是”red”了。

自定义指令可以嵌套内容,和预定义指令相似:<#if ...>nested content</#if>。比如,下面这个例子中是创建了一个可以为嵌套的内容画出边框:
<#macro border>
<table border=4 cellspacing=0 cellpadding=4><tr><td>
<#nested>
</tr></td></table>
</#macro>
<#nested>指令执行位于开始和结束标记指令之间的模板代码段。如果这样写:
<@border>The bordered text</@border>
将会输出如下内容:
<table border=4 cellspacing=0 cellpadding=4><tr><td>
The bordered text

nested指令也可以多次被调用,例如:
<#macro do_thrice>
<#nested>
<#nested>
<#nested>
</#macro>
<@do_thrice>
Anything.
</@do_thrice>
输出:
Anything.
Anything.
Anything.
</td></tr></table>

如果不使用nested指令,那么嵌套的内容就不会执行,如果不小心将greet指令写成了这样:
<@greet person="Joe">
Anything.
</@greet>
那么Anything会被忽略。

内嵌效果需要在定义宏变量时就指定<#nested>

<#macro repeat count>
<#local y = "test">
<#list 1..count as x>
${y} ${count}/${x}: <#nested>
</#list>
</#macro>
<@repeat count=3>${y!"?"} ${x!"?"} ${count!"?"}</@repeat>
打印内容
test 3/1: ? ? ?
test 3/2: ? ? ?
test 3/3: ? ? ?

 

 像list这样的预定义指令可以使用循环变量,自定义指令也可以有循环变量.

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

在使用的时候才给定参数。

当运行FTL模板时,就会有使用assign和macro指令创建的变量的集合(可能是空的)。像这样的变量集合被成为namespace命名空间。在简单的情况下可以只使用一个命名空间,称之为main namespace主命名空间。因为通常只使用本页上的命名空间,所以就没有意识到这点。
如果想创建可以重复使用的宏,函数和其他变量的集,使用多个命名空间是必然的,通常用术语来说就是引用library库。只要考虑你在一些项目中,或者想和他人共享使用的时候,你是否有一个很大的宏的集合。但要确保库中没有宏(或其他变量)名和数据模型中变量同名,而且也不能和模板中引用其他库中的变量同名。通常来说,变量因为名称冲突也会相互碰撞。所以要为每个库中的变量使用不同的命名空间。

zst.ftl文件有如下宏的定义:
<#macro copyright date>
    <p>copyright(C) ${date} zengshaotao </p>
</#macro>
<#assign mail ="jsmith@huateng.com">
要想在zzz.ftl模版文件使用,可以选择使用<#include>指令,但是这个时候就会在引用该包含指令的文件里创建两个隐藏的变量(一个是宏,一个是变量),所以存在变量被覆盖的问题,而使用import指令就会以新的数据模型来呈现。

假定zzz.ftl文件内容如下:
<#import "/lib/my_test.ftl" as my> <#-- the hash called "my" will be the "gate" -->
<@my.copyright date="1999-2002"/>
${my.mail}
要注意它是怎么访问为lib/my_test.ftl创建的命名空间中的变量的,通过新创建的哈希表,my。那么将会打印出:
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.</p>
jsmith@acme.com

修改zst.ftl文件的宏定义如下:
<#macro copyright date>
<p>Copyright (C) ${date} Julia Smith. All rights reserved.
<br>Email: ${mail}</p>
</#macro>

修改zzz.ftl文件内容如下:
<#import "/lib/my_test.ftl" as my>
<#assign mail="fred@acme.com">
<@my.copyright date="1999-2002"/>
${my.mail}
${mail}
将会输出:
<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.
<br>Email: jsmith@acme.com</p>
jsmith@acme.com
fred@acme.com

偶尔想要在一个被包含的命名空间上创建或替换一个变量。那么可以使用assign指令在完成,这个时候需要用到了它的namespace变量,也即是哈希变量。
<#import "/lib/my_test.ftl" as my>
${my.mail}
<#assign mail="jsmith@other.com" in my>
${my.mail}

在通常一些应用中,你也许想在模板中创建所有命名空间都可见的变量,就像数据模型中的变量一样。但是你不能在模板中改变数据模型,却可以通过global指令来达到相似的效果。

命名空间由使用的import指令中所写的路径来识别。如果想多次import这个路径,那么只会为第一次的import引用创建命名空间执行模板。后面相同路径的import只是创建一个哈希表当作访问相同命名空间的“门“。也就是相当于句柄。虽然是不同的门,但是访问的都是相同的变量。改变一个就全都改变了。

还要注意命名空间是不分层次的,它们相互之间是独立存在的。那么,如果在命名空间N1中import命名空间N2,那N2也不在N1中,N1只是可以通过哈希表来访问N2。这和在主命名空间中importN2,然后直接访问命名空间N2是一样的过程。

替换语法(方括号)和默认语法(尖括号)在一个模板中是相互排斥的。那就是说,整个模板要么全使用替换语法,要么全使用默认语法。如果模板使用了代替语法,那么如<#if ...>这样的东西就会被算作是静态文本,而不是FTL标签。类似地,如果模板使用默认语法,那么如[#if ...]这样的也会被算作是静态文本,而不是FTL标签。

分享到:
评论

相关推荐

    freemarker基础学习.pdf

    freemarker基础学习,是一本值得研究的书籍。对于初学者来说非常有用。

    freemarker基础v1.1.pdf

    在示例的`pom.xml`中,我们看到父工程指定了Spring Boot的版本为2.1.3.RELEASE,子工程`test-freemarker`包含了必要的依赖,如`spring-boot-starter-freemarker`和`spring-boot-starter-web`,这些依赖使得项目能够...

    freemarker基础

    在本资料中,我们将深入探讨Freemarker的基础知识,包括其基本语法、数据模型、模板设计以及如何在实际项目中使用它。 1. **Freemarker语法** Freemarker的核心是模板语言,由控制结构(如条件语句和循环)、变量...

    FreeMarker的基础知识整理

    FreeMarker 是一种强大的模板语言,主要用于生成动态内容,如HTML页面。...FreeMarker的核心概念是将静态的...对于初学者来说,理解FreeMarker的基础知识,如变量类型、模板结构和插值机制,是掌握这一技术的关键步骤。

    FreeMarker基础语法

    根据提供的文件信息,我们可以深入探讨FreeMarker的基础语法及其在模板引擎中的应用。FreeMarker是一种用于生成文本输出的模板引擎,广泛应用于Web开发中,能够帮助开发者动态生成HTML、XML等格式的内容。接下来,...

    freemarkerdemo 生成word 插入图片

    1. **Freemarker基础知识**:Freemarker是一个基于模板的语言,它允许开发者通过定义模板文件,然后结合Java对象数据,生成动态内容。模板文件中包含了一系列控制结构(如条件语句、循环)和变量引用,这些变量可以...

    freemarker中文学习资料

    1. **Freemarker基础概念** - **模板语言**:Freemarker使用一种简单的、声明式的模板语言,允许开发者编写模板,与后台数据模型结合,生成动态内容。 - **数据模型**:Freemarker模板与应用程序的数据模型进行...

    Freemarker实现excel导出功能

    一、Freemarker基础 1. 模板语言:Freemarker是一种基于模板的语言,它允许开发者通过简单的语法(如 `${}` 和 `#if`)来动态地生成文本输出,如HTML、XML或者,如我们所关注的,Excel文件。 2. 数据模型:在使用...

    freemarker 简单项目示例

    1. **Freemarker基础** - Freemarker是一个基于模板的开源Java库,它允许开发者通过定义模板语言(FTL,Freemarker Template Language)与数据模型相结合,生成动态内容。 - FTL是一种声明式语言,它不包含任何...

    freemarker培训课件

    标题:"Freemarker培训课件" 描述:"Freemarker培训,非常通俗,易懂,请多提宝贵意见" 标签:"Freemarker" 从标题和描述中提取的关键知识点是关于Freemarker的基本概念、其功能和用途,以及如何进行模板开发和...

    freemarker生成doc方案

    一、Freemarker基础 Freemarker是一个基于模板的语言,它与编程语言不同,它专注于数据模型和视图的分离。在Java应用中,你可以创建一个Freemarker模板,将数据模型注入其中,然后Freemarker会根据模板和数据生成...

    freemarker 教程 使用手册

    一、Freemarker基础 1. 模板语言:Freemarker是一种声明式语言,它不包含任何控制结构(如循环、条件语句),而是通过特定的语法来表达数据与模板的结合方式。 2. 变量与数据模型:在Freemarker中,变量是由`${}`...

    excel 导出 freemarker

    一、FreeMarker基础 FreeMarker是一个基于模板的Java库,它允许我们将数据模型与HTML或其他类型的模板结合,生成动态内容。FreeMarker模板语言(FTL)是模板中使用的标记语言,用于控制结构和逻辑。它与Java代码分离...

    freemarker基础代码

    在FreeMarker的基础实现中,有几个核心概念和关键知识点: 1. **模板(Template)**:模板是FreeMarker的基石,它定义了如何展示数据。模板文件通常以`.ftl`为扩展名,其中包含FreeMarker语法,如`${expression}`...

    FreeMarker应用实例和PPT

    - **FreeMarker基础**:解释FreeMarker的基本语法和结构。 - **Struts2整合步骤**:展示如何在Struts2项目中添加FreeMarker支持,配置文件设置,Action和模板的关联。 - **模板示例**:展示一个完整的FreeMarker...

    实用方便freemarker.jar freemarker架包 freemarker生成excel、word、html、xml例子

    1. FreeMarker基础: FreeMarker是一个基于模板的语言,它与编程语言(如Java)分离,允许开发者将数据模型和页面展示逻辑分开。它的核心概念是模板和数据模型。模板是HTML、XML或其他格式的文本文件,其中包含可...

    FreeMarker 设计指南

    一、FreeMarker基础 1. **模板语言**:FreeMarker使用模板语言,它是一种非编程语言,主要用于动态生成HTML或其他文本格式的文档。模板语言包含控制结构(如条件语句和循环)和变量表达式,它们与后台Java代码交互...

    freemarker获取数据

    一、Freemarker基础 1. 模板语言:Freemarker使用一种简单的文本模板语言,它不包含任何编程语句,只有控制结构(如`if`、`for`)和变量引用。变量通常以`${}`或`#set`指令表示。 2. 数据模型:Freemarker与后端...

    freemarker导出word完整案例

    一、Freemarker基础 1. 模板语法:Freemarker的模板由文本和控制结构(如条件语句、循环)组成,其中 `${expression}` 用于输出变量,`&lt;#if&gt;`、`&lt;#foreach&gt;` 等用于控制流程。例如,`${user.name}` 可以输出用户...

    freemarker教程

    一、Freemarker基础 1. 模板语法:Freemarker的模板语言由简单的文本和特殊的指令组成。例如,`${expression}`用于插入变量值,`&lt;#if condition&gt;`和`&lt;#else&gt;`用于条件判断,`&lt;#list items as item&gt;`用于循环遍历。 ...

Global site tag (gtag.js) - Google Analytics