`
zengshaotao
  • 浏览: 787807 次
  • 性别: 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模板引擎

    总结来说,Freemarker模板引擎在Java Web开发中扮演着重要角色,它简化了视图层的构建,通过与MyBatis等持久层框架配合,实现了高效的数据绑定和渲染。同时,结合ItripHotelRoom相关类,我们可以看到一个典型的业务...

    Java项目中利用Freemarker模板引擎导出--生成Word文档

    在这里将通过Freemarker这个模板引擎来实现导出 Word,项目不限于Swing,SSH,SSM,Spring Boot 之类的 ————————————— Spring Boot,Freemarker 编辑好格式的Word文档 1份 将Word文档里需要填充的地方...

    本oa办公系统基于springboot框架,选用了mysql数据库,前端采用freemarker模板引擎.zip

    本oa办公系统基于springboot框架,选用了mysql数据库,前端采用freemarker模板引擎.zip 1、该资源内项目代码经过严格调试,下载即用确保可以运行! 2、该资源适合计算机相关专业(如计科、人工智能、大数据、数学、...

    java web项目无刷新导出word文档demo,使用freemarker模板引擎

    本项目提供的就是一个无刷新导出Word文档的示例,它利用了FreeMarker模板引擎来实现这一功能。 FreeMarker是一个强大的、轻量级的模板语言,它主要用于生成动态内容,如HTML、XML、Word文档等。在这个项目中,...

    基于Java语言的freeMarker模板引擎设计源码解析与优化

    该项目深入解析并优化了基于Java语言的FreeMarker模板引擎,源码包含24个文件,其中包括12个Java源文件、4个FTL模板文件、3个XML配置文件、2个属性文件以及其他类型文件。项目结构清晰,旨在提升模板引擎的性能与...

    FreeMarker模板引擎资料大全

    FreeMarker 是一款模板引擎:即一种基于模板、用来生成输出文本(任何来自于 HTML格式,pdf格式的文本用来自动生成源代码)的通用工具。它是为 Java 程序员提供的一个开发包,本教程绝对详细,叫你从精通,玩转它

    基于SpringBoot实现的生成工资条源代码,使用FreeMarker模板引擎, iTextPdf生成工资条PDF

    在这个项目中,我们看到标题和描述提到了使用SpringBoot来实现工资条的生成,这涉及到两个关键的技术:FreeMarker模板引擎和iTextPdf库。 首先,FreeMarker是一个强大的模板引擎,常用于动态生成HTML或其他类型的...

    使用SpringBoot+Vue开发,文件模板使用FreeMarker模板引擎创建,该引擎允许

    使用SpringBoot+Vue开发,文件模板使用FreeMarker模板引擎创建,该引擎允许通过脚手架进行自定义加载和修改,以完成项目创建和生成,Vue页面通过可视化页面生成。基于数据库和数据表的代码生成

    -Panda_face-使用FreeMarker模板引擎实现一个自动代码生成工具,该工具可以

    -Panda_face-使用FreeMarker模板引擎实现一个自动代码生成工具,该工具可以根据数据库表自动生成实体、dao、servlet和简单的表单页面

    基于SSM框架和freemarker模板引擎开发的一套p2p借款平台源代码+数据库+毕业论文

    这是一套采用SSM框架和freemarker模板引擎开发的一套p2p借款平台, 外部引用了阿里云的手机实名认证接口,美联软通的短信发送接口和腾讯邮箱的发件接口。 系统简介 系统包含两类用户,普通用户和管理员。下面展示...

    SpringBoot+FreeMarker模板引擎demo

    FreeMarker 是一款模板引擎:一种基于模板的、用来生成输出文本(任何来自于 HTML 格式的文本用来自动生成源代码)的通用工具。它是为 Java 程序员提供的一个开发包或者说是类库。它不是面向最终用户,而是为程序员...

    基于Freemarker模板的代码生成器工具

    本篇将重点介绍一款名为“基于Freemarker模板的代码生成器工具”,这是一款纯Java实现的工具,利用了Freemarker模板引擎的强大功能。 **一、Freemarker模板引擎** Freemarker是一个开源的模板语言,用于生成动态...

    java使用freemarker模板技术导出word

    Java 使用 FreeMarker 模板技术导出 Word 是一种常见的数据动态生成文档的方法,它结合了 Java 的编程能力和 FreeMarker 模板引擎的强大功能,能够帮助开发者高效地生成结构化的 Word 文档。FreeMarker 是一个开源的...

    可视化div布局 生成freemarker模板

    1. **FreeMarker模板引擎**:FreeMarker是一个开源的Java模板引擎,它允许开发者将逻辑与表现分离。在Web开发中,FreeMarker用来动态生成HTML或其他类型的文本,而无需在模板中嵌入Java代码。FreeMarker模板语言...

    使用freeMarker模板和Spring boot后端API接口实现查询用户列表的功能。

    当前端(可能是浏览器)发送请求到`http://localhost:8080/ftl/index`时,Spring Boot会调用`getUserList`方法获取用户列表,然后将结果传给FreeMarker模板引擎。FreeMarker引擎将根据模板文件`index.ftl`的指令,...

    SpringBoot使用FreeMarker模板发送邮件

    通过springboot 整合freemarker模板引擎,自动发送html格式邮件

    Java freemarker 模板生成word动态表格

    1. **FreeMarker模板引擎**:FreeMarker是一个独立于任何Web框架的Java库,它的主要任务是将模板(.ftl文件)和数据模型结合起来,生成文本输出。模板语言是声明式的,这意味着你只需要描述“应该怎样显示”,而不是...

    Java利用Freemarker模板自动生成dto、dao、rowmapper、bo、service代码

    本主题涉及的核心技术是使用Freemarker模板引擎来生成DTO(Data Transfer Object)、DAO(Data Access Object)、RowMapper、BO(Business Object)和服务层代码。这些组件在Spring框架中扮演着重要角色。 1. **...

    FreeMarker模板基本语法

    ### FreeMarker模板基本语法 #### 一、FreeMarker概述与基本用法 ...它通过将数据模型与表现层分离的方式...上述介绍仅涵盖了FreeMarker模板引擎的一部分基础内容,更多的高级特性还需要开发者在实践中不断探索和学习。

    FreeMarker模板引擎 v2.3.30

    为您提供FreeMarker模板引擎下载,FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序。虽然FreeMarker具有一些...

Global site tag (gtag.js) - Google Analytics