FreeMarker奉行 模板+数据模型(data model) = 输出
模板所能用的数据被包装成数据模型,数据模型的创建是通过已经存在的程序计算得到的。
数据模式像是树形结构
(root)
|--------user = "Big Joe"
|-------- latestProduct
|------- url = "products/greenmouse.html"
|------- name = "green mouse"
上图中变量扮演目录的角色(root、latestProduct)被称为哈希表,哈希表通过可查找的名称(user、url、name)来访问储存的其他变量
如果要在模板中使用子变量,那应该从根root开始指定它的路径,每级之间用点来分隔。如root.user,root.latest.Product.url
数据模型可以被看做是树状结构的。
标量存储单一的值,这种类型的值可以是字符串,数字,日期/时间或者是布尔值。
哈希表是存储变量和与其相关且有唯一标识名称变量的容器。
序列是存储有序变量的容器。存储的变量可以通过数字索引来检索,索引通常从零开始。
${…}:FreeMarker将会输出真实的值来替换花括号内的表达式,这样的表达式被称为interpolations插值.
Comments注释:FreeMarker的注释和HTML的注释相似,但是它用<#--和-->来分隔的。任何介于这两个分隔符(包含分隔符本身)之间内容会被FreeMarker忽略,就不会输出出来了。
if指令
<#if animals.python.price < animals.elephant.price>
Pythons are cheaper than elephants today.
<#else>
Pythons are not cheaper than elephants today.
</#if>
list指令
<#list animals as being>
<tr><td>${being.name}<td>${being.price} Euros
</#list>
include指令 使用include指令,我们可以在当前的模板中插入其他文件的内容。
<#include "/copyright_footer.html">
FreeMarker不能容忍存在不存在之变量,除非明确表示如何处理。通常在!号后加个默认值。例如
${user$"Anonymous"}
当user不存在时降置值为"Anonymous"
当然也可以在变量名后面通过放置??来询问FreeMarker一个变量是否存在。将它和if指令合并,那么如果user变量不存在的话将会忽略整个问候代码段:
<#if user??><h1>Welcome ${user}!</h1></#if>
数据类型
标量: 字符串 数字 布尔值 日期
容器: 哈希表 序列 集
子程序:方法和函数 用户自定义指令
其它/很少使用: 节点
在内部,模板中可用的变量都是实现了freemarker.template.TemplateModel接口的Java对象。但在你自己的数据模型中,可以使用基本的Java集合类作为变量,因为这些变量会在内部被替换为适当的TemplateModel类型。这种功能特性被称作是object wrapping对象包装。对象包装功能可以透明地把任何类型的对象转换为实现了TemplateModel接口类型的实例。这就使得下面的转换成为可能,如在模板中把java.sql.ResultSet转换为序列变量,把javax.servlet.ServletRequest对象转换成包含请求属性的哈希表变量,甚至可以遍历XML文档作为FTL变量。
模板实现时会将非TemplateModel对象替换为TemplateModel对象。通过ObjectWrapper实现类的 的 TemplateModeal wrap(java.lang.Object)方法实现。
ObjectWrapper.DEFAULT_WRAPPER:它使用SimpleScalar来替换String,SimpleNumber来替换Number,SimpleSequence来替换List和数组,SimpleHash来替换Map,TemplateBooleanModel.TRUE或TemplateBooleanModel.FALSE来替换Boolean,freemarker.ext.dom.NodeModel来替换W3C组织定义的DOM模型节点类型。对于Jython类型的对象,包装器会调用freemarker.ext.jython.JythonWrapper。而对于其他对象,则会调用BEAN_WRAPPER。
ObjectWrapper.BEANS_WRAPPER:它可以通过Java 的反射机制来获取到Java Bean的属性和其他任意对象类型的成员变量。
*哈希表的自变量搜索方法与java bean的变量方法相同,不可同时实现。默认状态下实现SimpleHashModel.
数值同时也可以表现为多种类型,尽管这样很少使用。看下面这个数据模型mouse,就又是字符串又是哈希表。
(root)
| ------ mouse ="Dioe"
| ------ age = 12
| ------ color = "white"
三种通用数据模型:标量、哈希表、序列
TemplateScalarModel、TemplateHashMadel、TemplateSequenceModel
Class xxx implements TempleScalarModel,TemplateHashModel
如此,xxx实现类mouse可以既表示字符串又表示哈希表
Macro
<#macro test>
Test text
</#macro>
<#-- call the macro: -->
<@test/>
自定义指令可以有多个参数。如下所示,再添加一个新的参数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中可使用${}等FreeMarker语句