1、、、、快速入门快速入门快速入门快速入门((((1))))模板模板模板模板+数据模型数据模型数据模型数据模型=输出输出输出输出FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码下面是一个例子:htmlheadtitleWelcome!/title/headbodyh1Welcome${user}!/h1pOurlatestproduct:ahref=${latestProduct.url}${latestProduct.name}/a!/body/html这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)至于user、latestProduct.url和latestProduct.name来自于数据模型(datamodel)数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型下面是一个可能的数据模型:(root)|+-user=BigJoe|+-latestProduct|+-url=products/greenmouse.html|+-name=greenmouse数据模型类似于计算机的文件系统,latestProduct可以看作是目录,而user、url和name看作是文件,url和name文件位于latestProduct目录中(这只是一个比喻,实际并不存在)当FreeMarker将上面的数据模型合并到模板中,就创建了下面的输出:htmlheadtitleWelcome!/title/headbodyh1WelcomeBigJoe!/h1pOurlatestproduct:ahref=products/greenmouse.htmlgreenmouse/a!/body/html((((2))))数据模型数据模型数据模型数据模型典型的数据模型是树型结构,可以任意复杂和深层次,如下面的例子:(root)|+-animals|||+-mouse|||||+-size=small|||||+-price=50|||+-elephant|||||+-size=large|||||+-price=5000|||+-python|||+-size=medium|||+-price=4999|+-test=Itisatest|+-whatnot|+-because=don'tknow类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字类似于文件的变量称为scalars,保存单值scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理)对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price另外一种变量是sequences,和hashes类似,只是不使用变量名字,而使用数字索引,如下面的例子:(root)|+-animals|||+-(1st)|||||+-name=mouse|||||+-size=small|||||+-price=50|||+-(2nd)|||||+-name=elephant|||||+-size=large|||||+-price=5000|||+-(3rd)|||+-name=python|||+-size=medium|||+-price=4999|+-whatnot|+-fruits|+-(1st)=orange|+-(2nd)=banana这种对scalars的访问使用索引,如animals[0].name((((3))))模板模板模板模板在FreeMarker模板中可以包括下面三种特定部分:${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始,在后面叙述)注释:包含在#--和--(而不是!--和--)之间下面是一些使用指令的例子:if指令#ifanimals.python.priceanimals.elephant.pricePythonsarecheaperthanelephantstoday.#elsePythonsarenotcheaperthanelephantstoday./#iflist指令pWehavetheseanimals:tableborder=1trthNamethPrice#listanimalsasbeingtrtd${being.name}td${being.price}Euros/#list/table输出为:pWehavetheseanimals:tableborder=1trthNamethPricetrtdmousetd50Eurostrtdelephanttd5000Eurostrtdpythontd4999Euros/tableinclude指令htmlheadtitleTestpage/title/headbodyh1Testpage/h1pBlahblah...#include/copyright_footer.html/body/html一起使用指令pWehavetheseanimals:tableborder=1trthNamethPrice#listanimalsasbeingtrtd#ifbeing.size=largeb/#if${being.name}#ifbeing.size=large/b/#iftd${being.price}Euros/#list/table2222、、、、数据模型数据模型数据模型数据模型((((1111))))基础基础基础基础在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes和sequences,其实还可以有其它更多的能力:scalars:存储单值hashes:充当其它对象的容器,每个都关联一个唯一的查询名字sequences:充当其它对象的容器,按次序访问方法:通过传递的参数进行计算,以新对象返回结果用户自定义FTL标记:宏和变换器通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子:(root)|+-mouse=Yerri|+-age=12|+-color=brownmouse既是scalars又是hashes,将上面的数据模型合并到下面的模板:${mouse}#--usemouseasscalar--${mouse.age}#--usemouseashash--${mouse.color}#--usemouseashash--输出结果是:Yerri12brown((((2222))))ScalarScalarScalarScalar变量变量变量变量Scalar变量存储单值,可以是:字符串:简单文本,在模板中使用引号(单引号或双引号)括起数字:在模板中直接使用数字值日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们布尔值:true或false,通常在#if…标记中使用((((3333))))hasheshasheshasheshashes、、、、sequencessequencessequencessequences和集合和集合和集合和集合有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型:hashes:具有一个唯一的查询名字和它包含的每个变量相关联sequences:使用数字和它包含的每个变量相关联,索引值从0开始集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由#list…指令使用的受限sequences((((4444))))方法方法方法方法方法变量通常是基于给出的参数计算值下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值:Theaverageof3and5is:${avg(3,5)}Theaverageof6and10and20is:${avg(6,10,20)}Theaverageofthepriceofpythonandelephantis:${avg(animals.python.price,animals.elephant.price)}((((5555))))宏和变换器宏和变换器宏和变换器宏和变换器宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性((((6666))))节点节点节点节点节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲述3333、、、、模板模板模板模板((((1111))))整体结构整体结构整体结构整体结构模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合:文本:直接输出Interpolation:由${和},或#{和}来限定,计算值替代输出FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出注释:由#--和--限定,不会输出下面是以一个具体模板例子:html[BR]head[BR]titleWelcome!/title[BR]/head[BR]body[BR]#--Greettheuserwithhis/hername--[BR]h1Welcome${user}!/h1[BR]pWehavetheseanimals:[BR]ul[BR]#listanimalsasbeing[BR]li${being.name}for${being.price}Euros[BR]/#list[BR]/ul[BR]/body[BR]/html[BR]是用于换行的特殊字符序列注意事项:FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的Interpolation只能在文本中使用FTL标记不能位于另一个FTL标记内部,例如:#if#include'foo'='bar'.../if注释可以位于FTL标记和Interpolation内部,如下面的例子:h1Welcome${user#--Thenameofuser--}!/h1[BR]pWehavetheseanimals:[BR]ul[BR]#list#--somecomment...--animalsas#--again...--being[BR]...多余的空白字符会在模板输出时移除((((2222))))指令指令指令指令在FreeMarker中,使用FTL标记引用指令有三种FTL标记,这和HTML标记是类似的:开始标记:#directivenameparameters