收藏 分销(赏)

FreeMarker-模板开发指南.doc

上传人:仙人****88 文档编号:11739550 上传时间:2025-08-11 格式:DOC 页数:28 大小:239KB 下载积分:10 金币
下载 相关 举报
FreeMarker-模板开发指南.doc_第1页
第1页 / 共28页
FreeMarker-模板开发指南.doc_第2页
第2页 / 共28页


点击查看更多>>
资源描述
FreeMarker概述 FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写 FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序 虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图) FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件 FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境 FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库 FreeMarker是免费的 FreeMarker特性 1、通用目标 能够生成各种文本:HTML、XML、RTF、Java源代码等等 易于嵌入到你的产品中:轻量级;不需要Servlet环境 插件式模板载入器:可以从任何源载入模板,如本地文件、数据库等等 你可以按你所需生成文本:保存到本地文件;作为Email发送;从Web应用程序发送它返回给Web浏览器 2、强大的模板语言 所有常用的指令:include、if/elseif/else、循环结构 在模板中创建和改变变量 几乎在任何地方都可以使用复杂表达式来指定值 命名的宏,可以具有位置参数和嵌套内容 名字空间有助于建立和维护可重用的宏库,或者将一个大工程分成模块,而不必担心名字冲突 输出转换块:在嵌套模板片段生成输出时,转换HTML转义、压缩、语法高亮等等;你可以定义自己的转换 3、通用数据模型 FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示 你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰 4、为Web准备 在模板语言中内建处理典型Web相关任务(如HTML转义)的结构 能够集成到Model2 Web应用框架中作为JSP的替代 支持JSP标记库 为MVC模式设计:分离可视化设计和应用程序逻辑;分离页面设计员和程序员 5、智能的国际化和本地化 字符集智能化(内部使用UNICODE) 数字格式本地化敏感 日期和时间格式本地化敏感 非US字符集可以用作标识(如变量名) 多种不同语言的相同模板 6、强大的XML处理能力 <#recurse> 和<#visit>指令(2.3版本)用于递归遍历XML树 在模板中清楚和直觉的访问XML对象模型 FreeMarker vs. Velocity 1、概述 Velocity是一个简单而且更加轻量级的工具,但是它没有达到FreeMarker能够做的许多任务,而且它的模板语言不是很强大 我们认为对于大多数应用程序,FreeMarker比Velocity工作更简单,因为: Ø使用Velocity,你需要寻找特定工具或各种工作环境来一次次的解决典型的模板创作任务,结果会浪费更多时间 Ø工作环境经常意味着在Velocity模板中直接使用Java对象的方法,这违反了简单、无编程HTML设计的观念 Ø或者将表示任务移到控制器代码中,这违反了MVC模式 使用FreeMarker,可以以out-of-the-box(如何翻译确切?)的方式实现Velocity所能做的   2、特性比较清单 下面是一个使用FreeMarker能够实现,而Velocity不能实现的不太全面的特性清单: (1)数字和日期支持 可以对任何数字类型进行算术运算和比较,包括精度类型 可以比较和显示(格式化)日期/时间值 (2)国际化 根据各种内建和定制的数字格式,格式化本地敏感的数字 根据各种内建和定制的日期格式,格式化本地敏感和时区敏感的日期 标识(变量名)可以包含非英语字符,如重音字符、阿拉伯字符、中文字符等 (3)循环处理 可以跳出循环 可以在循环外访问循环体内的控制变量 可以测试是否达到最后一次循环 (4)模板级别的数组处理 可以使用类似[i]语法的索引方式访问数组元素 可以查询数组长度 (5)宏 宏可以有局部变量 可以递归调用宏,同样可以在模板的后面定义要调用的宏 调用宏时,可以按位置或名字的方式传递参数 宏参数可以有缺省值,使得在调用时忽略参数也有效 调用的宏可以有嵌套的体内容(<@myMacro>body</@myMacro>),能够在宏被调用时进行处理 宏是纯变量的,可以基于表达式来执行宏,或者作为参数传递给另一个宏 (6)命名空间 可以对变量使用多命名空间,这对创建宏库很重要,因为这可以避免应用程序中指定的变量和宏库中变量的名字冲突 (7)使用内建的函数/操作符维护Java无关的string、list和map 可以将字符串转换成大/小写、首字符大/小写,对HTML、XML或RTF进行转义处理,substring、split、查询字符串长度、find/replace子串等等 通过索引访问list元素,获得子list,合并list,查询list长度,对list排序 通过key变量访问map元素,检查map是否为空,获得key或值的list (8)揭示模板中的错误 当访问一个未定义的变量,FreeMarker不会沉默;你可以配置FreeMarker来停止render模板显示错误信息,或者跳过错误部分;无论哪种,FreeMarker会记录问题(日志) 在写错指令名时,FreeMarker会抛出异常 (9)高级render控制 可以使用一组标记来封装模板的一块区域,以便在块区中所有要修改的地方应用HTML或XML转义(或其它使用FreeMarker表达式表示的转换) FreeMarker有转换器,它们是模板的一块区域,在render时,通过转换过滤;内建的转换器包括空白字符压缩、HTML和XML转义;你可以实现自己的转换器;当然转换器可以嵌套 可以使用flush指令显式的flush输出 可以使用stop指令停止render (10)文字 除了通常的字符串、数字和布尔值文字,也可以在模板中定义list和map文字 支持所有的Java转义文字:\b、\t、\n、\f、\r、\”、\’、\\,也支持\xXXXX使用UNICODE指定字符 (11)高级空白字符移除 FreeMarker坚持移除各行只包含不输出FreeMarker标记的空白字符 对于明显要整修掉不需要的空白字符的指令来说,空白字符是个大问题 (12)集成其它技术 可以在模板中使用JSP标记库 可以直接在Python工程中使用 (13)强大的XML转换能力 在2.3版本中,FreeMarker具有强大的新XML转换能力,使得替代XSLT成为可能 Velocity在这方面是无法真正竞争的,除非改进核心引擎,如支持宏库映射到名字空间,宏中支持局部变量 (14)高级模板元程序 可以捕获输出的任何部分到context变量中 可以解释任何context变量,如果它是一个模板定义 上述两者的结合使用 FreeMarker设计指南(1) 1、快速入门 (1)模板 + 数据模型 = 输出 l         FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念 l         他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据 l         经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的 l         在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码 l         下面是一个例子: <html> <head>   <title>Welcome!</title> </head> <body>   <h1>Welcome ${user}!</h1>   <p>Our latest product:   <a href="${latestProduct.url}">${latestProduct.name}</a>! </body> </html>  l         这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template) l         至于user、latestProduct.url和latestProduct.name来自于数据模型(data model) l         数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成 l         模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型 l         下面是一个可能的数据模型: (root)   |   +- user = "Big Joe"   |   +- latestProduct       |       +- url = "products/greenmouse.html"       |       +- name = "green mouse" l         数据模型类似于计算机的文件系统,latestProduct可以看作是目录,而user、url和name看作是文件,url和name文件位于latestProduct目录中(这只是一个比喻,实际并不存在) l         当FreeMarker将上面的数据模型合并到模板中,就创建了下面的输出: <html> <head>   <title>Welcome!</title> </head> <body>   <h1>Welcome Big Joe!</h1>   <p>Our latest product:   <a href="products/greenmouse.html">green mouse</a>! </body> </html>  (2)数据模型 l         典型的数据模型是树型结构,可以任意复杂和深层次,如下面的例子: (root)   |   +- animals   |   |   |   +- mouse   |   |   |     |   |   +- size = "small"   |   |   |     |   |   +- price = 50   |   |   |   +- elephant   |   |   |     |   |   +- size = "large"   |   |   |     |   |   +- price = 5000   |   |   |   +- python   |       |     |       +- size = "medium"   |       |     |       +- price = 4999   |   +- test = "It is a test"   |   +- whatnot       |       +- because = "don't know" l         类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字 l         类似于文件的变量称为scalars,保存单值 l         scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理) l         对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price l         另外一种变量是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" l         这种对scalars的访问使用索引,如animals[0].name (3)模板 l         在FreeMarker模板中可以包括下面三种特定部分: Ø         ${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代 Ø         FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始,在后面叙述) Ø         注释:包含在<#--和-->(而不是<!--和-->)之间 l         下面是一些使用指令的例子: Ø         if指令 <#if animals.python.price < animals.elephant.price>   Pythons are cheaper than elephants today. <#else>   Pythons are not cheaper than elephants today. </#if>  Ø         list指令 <p>We have these animals: <table border=1>   <tr><th>Name<th>Price   <#list animals as being>   <tr><td>${being.name}<td>${being.price} Euros   </#list> </table>  输出为: <p>We have these animals: <table border=1>   <tr><th>Name<th>Price   <tr><td>mouse<td>50 Euros   <tr><td>elephant<td>5000 Euros   <tr><td>python<td>4999 Euros </table>  Ø         include指令 <html> <head>   <title>Test page</title> </head> <body>   <h1>Test page</h1>   <p>Blah blah... <#include "/copyright_footer.html"> </body> </html>  Ø         一起使用指令 <p>We have these animals: <table border=1>   <tr><th>Name<th>Price   <#list animals as being>   <tr>     <td>       <#if being.size = "large"><b></#if>       ${being.name}       <#if being.size = "large"></b></#if>     <td>${being.price} Euros   </#list> </table>  2、数据模型 (1)基础 l         在快速入门中介绍了在模板中使用的三种基本对象类型:scalars、hashes 和sequences,其实还可以有其它更多的能力: Ø         scalars:存储单值 Ø         hashes:充当其它对象的容器,每个都关联一个唯一的查询名字 Ø         sequences:充当其它对象的容器,按次序访问 Ø         方法:通过传递的参数进行计算,以新对象返回结果 Ø         用户自定义FTL标记:宏和变换器 l         通常每个变量只具有上述的一种能力,但一个变量可以具有多个上述能力,如下面的例子: (root) | +- mouse = "Yerri"      |      +- age = 12      |      +- color = "brown">  l         mouse既是scalars又是hashes,将上面的数据模型合并到下面的模板: ${mouse}       <#-- use mouse as scalar --> ${mouse.age}   <#-- use mouse as hash --> ${mouse.color} <#-- use mouse as hash -->  l         输出结果是: Yerri 12 brown  (2)Scalar变量 l         Scalar变量存储单值,可以是: Ø         字符串:简单文本,在模板中使用引号(单引号或双引号)括起 Ø         数字:在模板中直接使用数字值 Ø         日期:存储日期/时间相关的数据,可以是日期、时间或日期-时间(Timestamp);通常情况,日期值由程序员加到数据模型中,设计者只需要显示它们 Ø         布尔值:true或false,通常在<#if …>标记中使用 (3)hashes 、sequences和集合 l         有些变量不包含任何可显示的内容,而是作为容器包含其它变量,者有两种类型: Ø         hashes:具有一个唯一的查询名字和它包含的每个变量相关联 Ø         sequences:使用数字和它包含的每个变量相关联,索引值从0开始 l         集合变量通常类似sequences,除非无法访问它的大小和不能使用索引来获得它的子变量;集合可以看作只能由<#list …>指令使用的受限sequences (4)方法 l         方法变量通常是基于给出的参数计算值 l         下面的例子假设程序员已经将方法变量avg放到数据模型中,用来计算数字平均值: The average of 3 and 5 is: ${avg(3, 5)} The average of 6 and 10 and 20 is: ${avg(6, 10, 20)} The average of the price of python and elephant is: ${avg(animals.python.price, animals.elephant.price)} (5)宏和变换器 l         宏和变换器变量是用户自定义指令(自定义FTL标记),会在后面讲述这些高级特性 (6)节点 l         节点变量表示为树型结构中的一个节点,通常在XML处理中使用,会在后面的专门章节中讲述 3、模板 (1)整体结构 l         模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合: Ø         文本:直接输出 Ø         Interpolation:由${和},或#{和}来限定,计算值替代输出 Ø         FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出 Ø         注释:由<#--和-->限定,不会输出 l         下面是以一个具体模板例子: <html>[BR] <head>[BR]   <title>Welcome!</title>[BR] </head>[BR] <body>[BR]   <#-- Greet the user with his/her name -->[BR]   <h1>Welcome ${user}!</h1>[BR]   <p>We have these animals:[BR]   <ul>[BR]   <#list animals as being>[BR]     <li>${being.name} for ${being.price} Euros[BR]   </#list>[BR]   </ul>[BR] </body>[BR] </html>  l         [BR]是用于换行的特殊字符序列 l         注意事项: Ø         FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的 Ø         Interpolation只能在文本中使用 Ø         FTL标记不能位于另一个FTL标记内部,例如: <#if <#include 'foo'>='bar'>...</if> Ø         注释可以位于FTL标记和Interpolation内部,如下面的例子: <h1>Welcome ${user <#-- The name of user -->}!</h1>[BR] <p>We have these animals:[BR] <ul>[BR] <#list <#-- some comment... --> animals as <#-- again... --> being>[BR] ...  Ø         多余的空白字符会在模板输出时移除 (2)指令 l         在FreeMarker中,使用FTL标记引用指令 l         有三种FTL标记,这和HTML标记是类似的: Ø         开始标记:<#directivename parameters> Ø         结束标记:</#directivename> Ø         空内容指令标记:<#directivename parameters/> l         有两种类型的指令:预定义指令和用户定义指令 l         用户定义指令要使用@替换#,如<@mydirective>...</@mydirective>(会在后面讲述) l         FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的: <ul> <#list animals as being>   <li>${being.name} for ${being.price} Euros   <#if use = "Big Joe">      (except for you) </#list> </#if> <#-- WRONG! --> </ul>  l         如果使用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息 l         FreeMarker会忽略FTL标记中的空白字符,如下面的例子: <#list[BR]   animals       as[BR]      being[BR] >[BR] ${being.name} for ${being.price} Euros[BR] </#list    >  l         但是,<、</和指令之间不允许有空白字符 (3)表达式 l         直接指定值 Ø         字符串 n         使用单引号或双引号限定 n         如果包含特殊字符需要转义,如下面的例子: ${"It's \"quoted\" and this is a backslash: \\"}   ${'It\'s "quoted" and this is a backslash: \\'}  输出结果是: It's "quoted" and this is a backslash: \   It's "quoted" and this is a backslash: \  n         下面是支持的转义序列: 转义序列 含义 \" 双引号(u0022) \' 单引号(u0027) \\ 反斜杠(u005C) \n 换行(u000A) \r Return (u000D) \t Tab (u0009) \b Backspace (u0008) \f Form feed (u000C) \l < \g > \a & \{ { \xCode 4位16进制Unicode代码 n         有一类特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子: ${r"${foo}"} ${r"C:\foo\bar"}  输出的结果是: ${foo} C:\foo\bar  Ø         数字 n         直接输入,不需要引号 n         精度数字使用“.”分隔,不能使用分组符号 n         目前版本不支持科学计数法,所以“1E3”是错误的 n         不能省略小数点前面的0,所以“.5”是错误的 n         数字8、+8、08和8.00都是相同的 Ø         布尔值 n         true和false,不使用引号 Ø         序列 n         由逗号分隔的子变量列表,由方括号限定,下面是一个例子: <#list ["winter", "spring", "summer", "autumn"] as x> ${x} </#list>  输出的结果是: winter spring summer autumn n         列表的项目是表达式,所以可以有下面的例子: [2 + 2, [1, 2, 3, 4], "whatnot"] n         可以使用数字范围定义数字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意数字范围没有方括号 n         可以定义反递增的数字范围,如5..2 Ø         散列(hash) n         由逗号分隔的键/值列表,由大括号限定,键和值之间用冒号分隔,下面是一个例子: {"name":"green mouse", "price":150} n         键和值都是表达式,但是键必须是字符串 l         获取变量 Ø         顶层变量: ${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头 Ø         从散列中获取数据 n         可以使用点语法或方括号语法,假设有下面的数据模型: (root) | +- book |   | |   +- title = "Breeding green mouses" |   | |   +- author |       | |       +- name = "Julia Smith" |       | |       +- info = "Biologist, 1923-1985, Canada" | +- test = "title"  下面都是等价的: book.author.name book["author"].name book.author.["name"] book["author"]["name"] n         使用点语法,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字是任意表达式的结果 Ø         从序列获得数据:和散列的方括号语法语法一样,只是方括号中的表达式值必须是数字;注意:第一个项目的索引是0 Ø         序列片断:使用[startIndex..endIndex]语法,从序列中获得序列片断(也是序列);startIndex和endIndex是结果为数字的表达式 Ø         特殊变量:FreeMarker内定义变量,使用.variablename语法访问 l         字符串操作 Ø         Interpolation(或连接操作) n         可以使用${..}(或#{..})在文本部分插入表达式的值,例如: ${"Hello ${user}!"} ${"${user}${user}${user}${user}"}  n         可以使用+操作符获得同样的结果 ${"Hello " + user + "!"} ${user + user + user + user} n         ${..}只能用于文本部分,下面的代码是错误的: <#if ${isBig}>Wow!</#if> <#if "${isBig}">Wow!</#if> 应该写成: <#if isBig>Wow!</#if> Ø         子串 n         例子(假设user的值为“Big Joe”): ${user[0]}${user[4]} ${user[1..4]} 结果是(注意第一个字符的索引是0): BJ ig J  l         序列操作 Ø         连接操作:和字符串一样,使用+,下面是一个例子: <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user> - ${user} </#list> 输出结果是: - Joe - Fred - Julia - Kate l         散列操作 Ø         连接操作:和字符串一样,使用+,如果具有相同的key,右边的值替代左边的值,例如: <#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}> - Joe is ${ages.Joe} - Fred is ${ages.Fred} - Julia is ${ages.Julia}  输出结果是: - Joe is 30 - Fred is 25 - Julia is 18  l         算术运算 Ø         +、-、×、/、%,下面是一个例子: ${x * x - 100} ${x / 2} ${12 % 10} 输出结果是(假设x为5): -75 2.5 2  Ø         操作符两边必须是数字,因此下面的代码是错误的: ${3 * "5"} <#-- WRONG! -->  Ø         使用+操作符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串,例如: ${3 + "5"}  输出结果是: 35 Ø         使用内建的int(后面讲述)获得整数部分,例如: ${(x/2)?int} ${1.1?int} ${1.999?int} ${-1.1?int} ${-1.999?int} 输出结果是(假设x为5): 2 1 1 -1 -1 l         比较操作符 Ø         使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等 Ø         =和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误 Ø         Freemarker是精确比较,所以对"x"、"x  "和"X"是不相等的 Ø         对数字和日期可以使用<、<=、>和>=,但不能用于字符串 Ø         由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)> Ø         另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>= l         逻辑操作符 Ø         &&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误 Ø         例子: <#if x < 12 && color = "green">   We have less than 12 things, and they are green. </#if> <#if !hot> <#-- here hot must be a boolean -->   It's not hot. </#if>  l         内建函数 Ø         内建函数的用法类似访问散列的子变量,只是使用“?”替代“.”,下面列出常用的一些函数 Ø         字符串使用的: n         html:对字符串进行HTML编码 n         cap_first:使字符串第一个字母大写 n         lower_case:将字符串转换成小写 n         upper_case:将字符串转换成大写 n         trim:去掉字符串前后的空白字符 Ø         序列使用的: n         size:获得序列中元素的数目 Ø         数字使用的: n         int:取得数字的整数部分(如-1.9?int的结果是-1) Ø         例子(假设test保存字符串"Tom & Jerry"): ${test?html} ${test?upper_case?html} 输出结果是: Tom &amp; Jerry TOM &amp; JERRY  l         操作符优先顺序 操作符组 操作符 后缀 [subvarName] [subStringRange] . (methodParams) 一元 +expr
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服