FreeMaker一篇通
- 格式:pdf
- 大小:1.16 MB
- 文档页数:10
FreeMarker概述●FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写●FreeMarker被设计用来生成HTML Web页面,特别是基于MVC模式的应用程序●虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)●FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件●FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境●FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库●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设计指南(1)1、快速入门(1)模板+ 数据模型= 输出●FreeMarker基于设计者和程序员是具有不同专业技能的不同个体的观念●他们是分工劳动的:设计者专注于表示——创建HTML文件、图片、Web页面的其它可视化方面;程序员创建系统,生成设计页面要显示的数据●经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的●在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码●下面是一个例子:●这个例子是在简单的HTML中加入了一些由${…}包围的特定代码,这些特定代码是FreeMarker的指令,而包含FreeMarker的指令的文件就称为模板(Template)●至于user、latestProduct.url和来自于数据模型(data model)●数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成●模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型●下面是一个可能的数据模型:●数据模型类似于计算机的文件系统,latestProduct可以看作是目录,而user、url和name看作是文件,url和name文件位于latestProduct目录中(这只是一个比喻,实际并不存在)●当FreeMarker将上面的数据模型合并到模板中,就创建了下面的输出:(2)数据模型典型的数据模型是树型结构,可以任意复杂和深层次,如下面的例子:●类似于文件的变量称为scalars,保存单值●scalars保存的值有两种类型:字符串(用引号括起,可以是单引号或双引号)和数字(不要用引号将数字括起,这会作为字符串处理)●对scalars的访问从root开始,各部分用“.”分隔,如animals.mouse.price●另外一种变量是sequences,和hashes类似,只是不使用变量名字,而使用数字索引,如下面的例子:(3)模板●在FreeMarker模板中可以包括下面三种特定部分:➢${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代➢FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML 标记区分,用#开始(有些以@开始,在后面叙述)➢注释:包含在<#--和-->(而不是<!--和-->)之间●下面是一些使用指令的例子:➢if指令➢list指令输出为:3、模板(1)整体结构●模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合:➢文本:直接输出➢Interpolation:由${和},或#{和}来限定,计算值替代输出➢FTL标记:FreeMarker指令,和HTML标记类似,名字前加#予以区分,不会输出➢注释:由<#--和-->限定,不会输出●下面是以一个具体模板例子:●注意事项:➢FTL区分大小写,所以list是正确的FTL指令,而List不是;${name}和${NAME}是不同的➢Interpolation只能在文本中使用➢FTL标记不能位于另一个FTL标记内部,例如:(2)指令●在FreeMarker中,使用FTL标记引用指令●有三种FTL标记,这和HTML标记是类似的:➢开始标记:<#directivename parameters>➢结束标记:</#directivename>➢空内容指令标记:<#directivename parameters/>●有两种类型的指令:预定义指令和用户定义指令●用户定义指令要使用@替换#,如<@mydirective>...</@mydirective>(会在后面讲述)●FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的:●FreeMarker会忽略FTL标记中的空白字符,如下面的例子:(3)表达式●直接指定值➢字符串⏹使用单引号或双引号限定⏹如果包含特殊字符需要转义,如下面的例子:输出结果是:转义序列含义\"双引号(u0022)\'单引号(u0027)\\反斜杠(u005C)\n换行(u000A)\r Return (u000D)\t Tab (u0009)\b Backspace (u0008)\f Form feed (u000C)\l<\g>\a&\{{\x Code4位16进制Unicode代码⏹有一类特殊的字符串称为raw字符串,被认为是纯文本,其中的\和{等不具有特殊含义,该类字符串在引号前面加r,下面是一个例子:⏹直接输入,不需要引号⏹精度数字使用“.”分隔,不能使用分组符号⏹目前版本不支持科学计数法,所以“1E3”是错误的⏹不能省略小数点前面的0,所以“.5”是错误的⏹数字8、+8、08和8.00都是相同的➢布尔值⏹true和false,不使用引号➢序列⏹由逗号分隔的子变量列表,由方括号限定,下面是一个例子:输出的结果是:⏹可以使用数字范围定义数字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意数字范围没有方括号⏹可以定义反递增的数字范围,如5..2➢散列(hash)⏹由逗号分隔的键/值列表,由大括号限定,键和值之间用冒号分隔,下面是一个例子:●获取变量➢顶层变量: ${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头➢从散列中获取数据⏹可以使用点语法或方括号语法,假设有下面的数据模型:下面都是等价的:因为名字是任意表达式的结果➢从序列获得数据:和散列的方括号语法语法一样,只是方括号中的表达式值必须是数字;注意:第一个项目的索引是0➢序列片断:使用[startIndex..endIndex]语法,从序列中获得序列片断(也是序列);startIndex和endIndex是结果为数字的表达式➢特殊变量:FreeMarker内定义变量,使用.variablename语法访问●字符串操作➢Interpolation(或连接操作)⏹可以使用${..}(或#{..})在文本部分插入表达式的值,例如:⏹可以使用+操作符获得同样的结果⏹${..}只能用于文本部分,下面的代码是错误的:应该写成:➢子串⏹例子(假设user的值为“Big Joe”):结果是(注意第一个字符的索引是0):●序列操作➢连接操作:和字符串一样,使用+,下面是一个例子:输出结果是:●散列操作➢连接操作:和字符串一样,使用+,如果具有相同的key,右边的值替代左边的值,例如:输出结果是:●算术运算➢+、-、×、/、%,下面是一个例子:输出结果是(假设x为5):➢操作符两边必须是数字,因此下面的代码是错误的:➢使用+操作符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串,例如:输出结果是:➢使用内建的int(后面讲述)获得整数部分,例如:输出结果是(假设x为5):●比较操作符➢使用=(或==,完全相等)测试两个值是否相等,使用!=测试两个值是否不相等➢=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误➢Freemarker是精确比较,所以对"x"、"x "和"X"是不相等的➢对数字和日期可以使用<、<=、>和>=,但不能用于字符串➢由于Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)>➢另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>=●逻辑操作符➢&&(and)、||(or)、!(not),只能用于布尔值,否则会产生错误➢例子:●内建函数➢内建函数的用法类似访问散列的子变量,只是使用“?”替代“.”,下面列出常用的一些函数➢字符串使用的:⏹html:对字符串进行HTML编码⏹cap_first:使字符串第一个字母大写⏹lower_case:将字符串转换成小写⏹upper_case:将字符串转换成大写⏹trim:去掉字符串前后的空白字符➢序列使用的:⏹size:获得序列中元素的数目➢数字使用的:⏹int:取得数字的整数部分(如-1.9?int的结果是-1)➢例子(假设test保存字符串"Tom & Jerry"):输出结果是:●操作符优先顺序操作符组操作符后缀[subvarName] [subStringRange]. (methodParams)一元+expr、-expr、!内建?乘法*、/ 、%加法+、-关系<、>、<=、>=(lt、lte、gt、gte)相等==(=)、!=逻辑and &&逻辑or ||数字范围..(4)Interpolation●Interpolation有两种类型:➢通用Interpolation:${expr}➢数字Interpolation:#{expr}或#{expr; format}●注意:Interpolation只能用于文本部分●通用Interpolation➢插入字符串值:直接输出表达式结果➢插入数字值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:输出结果是:➢插入日期值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个使用格式模式的例子:输出的结果类似下面的格式:➢插入布尔值:根据缺省格式(由#setting指令设置)将表达式结果转换成文本输出;可以使用内建函数string格式化单个Interpolation,下面是一个例子:输出结果是:●数字Interpolation的#{expr; format}形式可以用来格式化数字,format可以是:➢mX:小数部分最小X位➢MX:小数部分最大X位➢例子:4、杂项(1)用户定义指令●宏和变换器变量是两种不同类型的用户定义指令,它们之间的区别是宏是在模板中使用macro指令定义,而变换器是在模板外由程序定义,这里只介绍宏●基本用法➢宏是和某个变量关联的模板片断,以便在模板中通过用户定义指令使用该变量,下面是一个例子:➢作为用户定义指令使用宏变量时,使用@替代FTL标记中的#➢如果没有体内容,也可以使用:●参数➢在macro指令中可以在宏变量之后定义参数,如:➢可以这样使用这个宏变量:输出结果是:➢宏的参数是FTL表达式,所以下面的代码具有不同的意思:➢这意味着将Fred变量的值传给person参数,该值不仅是字符串,还可以是其它类型,甚至是复杂的表达式➢宏可以有多参数,下面是一个例子:➢可以这样使用该宏变量:➢其中参数的次序是无关的,因此下面是等价的:➢只能使用在macro指令中定义的参数,并且对所有参数赋值,所以下面的代码是错误的:➢可以在定义参数时指定缺省值,如:➢这样<@greet person="Fred"/>就正确了➢宏的参数是局部变量,只能在宏定义中有效●嵌套内容➢用户定义指令可以有嵌套内容,使用<#nested>指令执行指令开始和结束标记之间的模板片断➢例子:这样使用该宏变量:输出结果:➢<#nested>指令可以被多次调用,例如:输出结果:➢嵌套内容可以是有效的FTL,下面是一个有些复杂的例子:输出结果:➢宏定义中的局部变量对嵌套内容是不可见的,例如:输出结果:➢●在宏定义中使用循环变量➢用户定义指令可以有循环变量,通常用于重复嵌套内容,基本用法是:作为nested指令的参数传递循环变量的实际值,而在调用用户定义指令时,在<@…>开始标记的参数后面指定循环变量的名字➢例子:输出结果:➢指定的循环变量的数目和用户定义指令开始标记指定的不同不会有问题⏹调用时少指定循环变量,则多指定的值不可见⏹调用时多指定循环变量,多余的循环变量不会被创建(2)在模板中定义变量●在模板中定义的变量有三种类型:➢plain变量:可以在模板的任何地方访问,包括使用include指令插入的模板,使用assign指令创建和替换➢局部变量:在宏定义体中有效,使用local指令创建和替换➢循环变量:只能存在于指令的嵌套内容,由指令(如list)自动创建;宏的参数是局部变量,而不是循环变量●局部变量隐藏(而不是覆盖)同名的plain变量;循环变量隐藏同名的局部变量和plain变量,下面是一个例子:输出结果:●内部循环变量隐藏同名的外部循环变量,如:输出结果:中的同名变量,使用特殊变量global,下面的例子假设数据模型中的user的值是Big Joe:(3)名字空间●通常情况,只使用一个名字空间,称为主名字空间●为了创建可重用的宏、变换器或其它变量的集合(通常称库),必须使用多名字空间,其目的是防止同名冲突●创建库➢下面是一个创建库的例子(假设保存在lib/my_test.ftl中):间,并可以通过import指令中指定的散列变量访问库中的变量:输出结果:可以看到例子中使用的两个同名变量并没有冲突,因为它们位于不同的名字空间●可以使用assign指令在导入的名字空间中创建或替代变量,下面是一个例子:●输出结果:●数据模型中的变量任何地方都可见,也包括不同的名字空间,下面是修改的库:Freemarker - 几个比较实用的例子- -用Freemarker做模本语言有一段时间了,列出几个和JSP或者Velocity相比起来比较方便的用途,目的是引诱更多的人跳上Freemarker这个贼船,1. String内置的JavaScript转换: js_string用途:用于JavaScript转义,转换',",换行等特殊字符模板:<script>alert("${errorMessage?js_string}");</script>输出:<script>alert("Readonly\'s pet name is \"Cross Bone\"");</script>2.内置的默认值处理:default用途: 用于处理默认值模本:User: ${?default("Anonymous")}<td>${()?default(" ")}</td >输出:User: Anonymous<td> </td>注,可以对整个对象树加上(),再用内置处理器这种方便的做法,偶也是最近刚学会的,以前一直用很傻的方法做.....3. Sequence内置的计数器: xxx_index用途:显示序号模板:<#list employees as e>${e_index}. ${}</#list>输出:1. Readonly2. Robbin4. Sequence内置的分段器: chunk用途:某些比较BT的排版需求模板:<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']><#list seq?chunk(4) as row><ul><li><#list row as cell>${cell} </#list></li></ul></#list><#list seq?chunk(4, '-') as row><tr><td><#list row as cell>${cell} </#list></td></tr></#list>输出:<ul><li>a</li> <li>b</li> <li>c</li> <li>d</li> </ul><ul><li>e</li> <li>f</li> <li>g</li> <li>h</li> </ul><ul><li>i</li> <li>j</li> </ul><tr><td>a</td><td>b</td> <td>c</td> <td>d</td> </tr><tr><td>e</td> <td>f</td> <td>g</td> <td>h</td> </tr><tr><td>i</td> <td>j</td> <td>-</td> <td>-</td> </tr>语法FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:1. 文本:直接输出的部分2. 注释:<#-- ... -->格式部分,不会输出3. 插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出4. FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出1.FTL指令规则在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的.1.开始标签:<#directivename parameter>2.结束标签:</#directivename>3.空标签:<#directivename parameter/>实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号.使用FTL标签时, 应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是< , /> 和指令之间不允许有空白字符.2.插值规则FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}2.1 通用插值对于通用插值,又可以分为以下4种情况:1. 插值结果为字符串值:直接输出表达式结果2. 插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:<#settion number_format="currency"/><#assign answer=42/>${answer}${answer?string} <#-- the same as ${answer} -->${answer?string.number}${answer?string.currency}${answer?string.percent}${answer}输出结果是:$42.00$42.0042$42.004,200%3. 插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}${lastUpdated?string("EEE, MMM d, ''yy")}${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}输出结果是:2008-04-08 08:08:08 Pacific Daylight TimeTue, Apr 8, '03Tuesday, April 08, 2003, 08:08:08 PM (PDT)4. 插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:<#assign foo=true/>${foo?string("yes", "no")}输出结果是:yes2.2 数字格式化插值数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:mX:小数部分最小X位MX:小数部分最大X位如下面的例子:<#assign x=2.582/><#assign y=4/>#{x; M2} <#-- 输出2.58 -->#{y; M2} <#-- 输出4 -->#{x; m2} <#-- 输出2.6 -->#{y; m2} <#-- 输出4.0 -->#{x; m1M2} <#-- 输出2.58 -->#{x; m1M2} <#-- 输出4.0 -->3.表达式表达式是FreeMarker模板的核心功能,表达式放置在插值语法${}之中时,表明需要输出表达式的值;表达式语法也可与FreeMarker 标签结合,用于控制输出.实际上FreeMarker的表达式功能非常强大,它不仅支持直接指定值,输出变量值,也支持字符串格式化输出和集合访问等功能.3.1 直接指定值使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象.1. 字符串直接指定字符串值使用单引号或双引号限定,如果字符串值中包含特殊字符需要转义,看下面的例子:${"我的文件保存在C:\\盘"}${'我名字是\"annlee\"'}输出结果是:我的文件保存在C:\盘我名字是"annlee"FreeMarker支持如下转义字符:\";双引号(u0022)\';单引号(u0027)\\;反斜杠(u005C)\n;换行(u000A)\r;回车(u000D)\t;Tab(u0009)\b;退格键(u0008)\f;Form feed(u000C)\l;<\g;>\a;&\{;{\xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码:${r"${foo}"}${r"C:\foo\bar"}输出结果是:${foo}C:\foo\bar2. 数值表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker目前还不支持科学计数法,所以"1E3"是错误的.在FreeMarker表达式中使用数值需要注意以下几点:a)数值不能省略小数点前面的0,所以".5"是错误的写法b)数值8 , +8 , 8.00都是相同的3. 布尔值直接使用true和false,不使用引号.4. 集合集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子:<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>${x}</#list>输出结果是:星期一星期二星期三星期四星期五星期六星期天除此之外,集合元素也可以是表达式,例子如下:[2 + 2, [1, 2, 3, 4], "whatnot"]还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..25,Map对象Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value 对之间以英文逗号","分隔.下面是一个例子:{"语文":78, "数学":80}Map对象的key和value都是表达式,但是key必须是字符串3.2 输出变量值FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况1. 顶层变量所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:Map root = new HashMap(); //创建数据模型root.put("name","annlee"); //name是一个顶层变量对于顶层变量,直接使用${variableName}来输出变量值,变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法: ${name}2. 输出集合元素如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引:["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法:${week[2]} //输出第三个集合元素此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法:week[3..5] //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素3. 输出Map元素这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:Map root = new HashMap();Book book = new Book();Author author = new Author();author.setName("annlee");author.setAddress("gz");book.setName("struts2");book.setAuthor(author);root.put("info","struts");root.put("book", book);为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法: //全部使用点语法book["author"].namebook.author["name"] //混合使用点语法和方括号语法book["author"]["name"] //全部使用方括号语法使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.3.3字符串操作FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等.字符串连接有两种语法:1. 使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接.2. 直接使用连接运算符+来连接字符串例如有如下数据模型:Map root = new HashMap(); root.put("user","annlee");下面将user变量和常量连接起来:${"hello, ${user}!"} //使用第一种语法来连接${"hello, " + user + "!"} //使用+号来连接上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样.值得注意的是,${..}只能用于文本部分,不能用于表达式,下面的代码是错误的:<#if ${isBig}>Wow!</#if><#if "${isBig}">Wow!</#if>应该写成:<#if isBig>Wow!</#if>截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型:Map root = new HashMap(); root.put("book","struts2,freemarker");可以通过如下语法来截取子串:${book[0]}${book[4]} //结果是su。
FreeMarker语法FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:1,文本:直接输出的部分2,注释:<#-- ... -->格式部分,不会输出3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出下面是一个FreeMarker模板的例子,包含了以上所说的4个部分<html><br><head><br><title>Welcome!</title><br></head><br><body><br><#-- 注释部分--><br><#-- 下面使用插值--><h1>Welcome ${user} !</h1><br><p>We have these animals:<br><u1><br><#-- 使用FTL指令--><#list animals as being><br><li>${} for ${being.price} Euros<br><#list><br><u1><br></body><br></html>1, FTL指令规则在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的.1,开始标签:<#directivename parameter>2,结束标签:</#directivename>3,空标签:<#directivename parameter/>实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号.使用FTL标签时, 应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是< , /> 和指令之间不允许有空白字符.2, 插值规则FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}2.1 通用插值对于通用插值,又可以分为以下4种情况:1,插值结果为字符串值:直接输出表达式结果2,插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:<#settion number_format="currency"/><#assign answer=42/>${answer}${answer?string} <#-- the same as ${answer} -->${answer?string.number}${answer?string.currency}${answer?string.percent}${answer}输出结果是:$42.00$42.0042$42.004,200%3,插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")}${lastUpdated?string("EEE, MMM d, ''yy")}${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}输出结果是:2008-04-08 08:08:08 Pacific Daylight TimeTue, Apr 8, '03Tuesday, April 08, 2003, 08:08:08 PM (PDT)4,插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:<#assign foo=true/>${foo?string("yes", "no")}输出结果是:yes2.2 数字格式化插值数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:mX:小数部分最小X位MX:小数部分最大X位如下面的例子:<#assign x=2.582/><#assign y=4/>#{x; M2} <#-- 输出2.58 -->#{y; M2} <#-- 输出4 -->#{x; m2} <#-- 输出2.6 -->#{y; m2} <#-- 输出4.0 -->#{x; m1M2} <#-- 输出2.58 -->#{x; m1M2} <#-- 输出4.0 -->3, 表达式表达式是FreeMarker模板的核心功能,表达式放置在插值语法${}之中时,表明需要输出表达式的值;表达式语法也可与FreeMarker 标签结合,用于控制输出.实际上FreeMarker的表达式功能非常强大,它不仅支持直接指定值,输出变量值,也支持字符串格式化输出和集合访问等功能.3.1 直接指定值使用直接指定值语法让FreeMarker直接输出插值中的值,而不是输出变量值.直接指定值可以是字符串,数值,布尔值,集合和MAP对象.1,字符串直接指定字符串值使用单引号或双引号限定,如果字符串值中包含特殊字符需要转义,看下面的例子:${"我的文件保存在C:\\盘"}${'我名字是\"annlee\"'}输出结果是:我的文件保存在C:\盘我名字是"annlee"FreeMarker支持如下转义字符:\";双引号(u0022)\';单引号(u0027)\\;反斜杠(u005C)\n;换行(u000A)\r;回车(u000D)\t;Tab(u0009)\b;退格键(u0008)\f;Form feed(u000C)\l;<\g;>\a;&\{;{\xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码: ${r"${foo}"}${r"C:\foo\bar"}输出结果是:${foo}C:\foo\bar2,数值表达式中的数值直接输出,不需要引号.小数点使用"."分隔,不能使用分组","符号.FreeMarker 目前还不支持科学计数法,所以"1E3"是错误的.在FreeMarker表达式中使用数值需要注意以下几点:1,数值不能省略小数点前面的0,所以".5"是错误的写法2,数值8 , +8 , 8.00都是相同的3,布尔值直接使用true和false,不使用引号.4,集合集合以方括号包括,各集合元素之间以英文逗号","分隔,看如下的例子:<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>${x}</#list>输出结果是:星期一星期二星期三星期四星期五星期六星期天除此之外,集合元素也可以是表达式,例子如下:[2 + 2, [1, 2, 3, 4], "whatnot"]还可以使用数字范围定义数字集合,如2..5等同于[2, 3, 4, 5],但是更有效率.注意,使用数字范围来定义集合时无需使用方括号,数字范围也支持反递增的数字范围,如5..25,Map对象Map对象使用花括号包括,Map中的key-value对之间以英文冒号":"分隔,多组key-value对之间以英文逗号","分隔.下面是一个例子:{"语文":78, "数学":80}Map对象的key和value都是表达式,但是key必须是字符串3.2 输出变量值FreeMarker的表达式输出变量时,这些变量可以是顶层变量,也可以是Map对象中的变量,还可以是集合中的变量,并可以使用点(.)语法来访问Java对象的属性.下面分别讨论这些情况1,顶层变量所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:Map root = new HashMap(); //创建数据模型root.put("name","annlee"); //name是一个顶层变量对于顶层变量,直接使用${variableName}来输出变量值,变量名只能是字母,数字,下划线,$,@和#的组合,且不能以数字开头号.为了输出上面的name的值,可以使用如下语法: ${name}2,输出集合元素如果需要输出集合元素,则可以根据集合元素的索引来输出集合元素,集合元素的索引以方括号指定.假设有索引:["星期一","星期二","星期三","星期四","星期五","星期六","星期天"].该索引名为week,如果需要输出星期三,则可以使用如下语法:${week[2]} //输出第三个集合元素此外,FreeMarker还支持返回集合的子集合,如果需要返回集合的子集合,则可以使用如下语法:week[3..5] //返回week集合的子集合,子集合中的元素是week集合中的第4-6个元素3,输出Map元素这里的Map对象可以是直接HashMap的实例,甚至包括JavaBean实例,对于JavaBean实例而言,我们一样可以把其当成属性为key,属性值为value的Map实例.为了输出Map元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:Map root = new HashMap();Book book = new Book();Author author = new Author();author.setName("annlee");author.setAddress("gz");book.setName("struts2");book.setAuthor(author);root.put("info","struts");root.put("book", book);为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法: //全部使用点语法book["author"].namebook.author["name"] //混合使用点语法和方括号语法book["author"]["name"] //全部使用方括号语法使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.3.3, 字符串操作FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等.字符串连接有两种语法:1,使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接.2,直接使用连接运算符+来连接字符串例如有如下数据模型:Map root = new HashMap(); root.put("user","annlee");下面将user变量和常量连接起来:${"hello, ${user}!"} //使用第一种语法来连接${"hello, " + user + "!"} //使用+号来连接上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样.值得注意的是,${..}只能用于文本部分,不能用于表达式,下面的代码是错误的:<#if ${isBig}>Wow!</#if><#if "${isBig}">Wow!</#if>应该写成:<#if isBig>Wow!</#if>截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型:Map root = new HashMap(); root.put("book","struts2,freemarker");可以通过如下语法来截取子串:${book[0]}${book[4]} //结果是su${book[1..4]} //结果是tru3.4 集合连接运算符这里所说的集合运算符是将两个集合连接成一个新的集合,连接集合的运算符是+,看如下的例子:<#list ["星期一","星期二","星期三"] + ["星期四","星期五","星期六","星期天"] as x>${x}</#list>输出结果是:星期一星期二星期三星期四星期五星期六星期天3.5 Map连接运算符Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:<#assign scores = {"语文":86,"数学":78} + {"数学":87,"Java":93}>语文成绩是${scores.语文}数学成绩是${scores.数学}Java成绩是${scores.Java}输出结果是:语文成绩是86数学成绩是87Java成绩是933.6 算术运算符FreeMarker表达式中完全支持算术运算,FreeMarker支持的算术运算符包括:+, - , * , / , % 看如下的代码:<#assign x=5>${ x * x - 100 }${ x /2 }${ 12 %10 }输出结果是:-75 2.5 2在表达式中使用算术运算符时要注意以下几点:1,运算符两边的运算数字必须是数字2,使用+运算符时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串再连接,如:${3 + "5"},结果是:35使用内建的int函数可对数值取整,如:<#assign x=5>${ (x/2)?int }${ 1.1?int }${ 1.999?int }${ -1.1?int }${ -1.999?int }结果是:2 1 1 -1 -13.7 比较运算符表达式中支持的比较运算符有如下几个:1,=或者==:判断两个值是否相等.2,!=:判断两个值是否不等.3,>或者gt:判断左边值是否大于右边值4,>=或者gte:判断左边值是否大于等于右边值5,<或者lt:判断左边值是否小于右边值6,<=或者lte:判断左边值是否小于等于右边值注意:=和!=可以用于字符串,数值和日期来比较是否相等,但=和!=两边必须是相同类型的值,否则会产生错误,而且FreeMarker是精确比较,"x","x ","X"是不等的.其它的运行符可以作用于数字和日期,但不能作用于字符串,大部分的时候,使用gt等字母运算符代替>会有更好的效果,因为FreeMarker会把>解释成FTL标签的结束字符,当然,也可以使用括号来避免这种情况,如:<#if (x>y)>3.8 逻辑运算符逻辑运算符有如下几个:逻辑与:&&逻辑或:||逻辑非:!逻辑运算符只能作用于布尔值,否则将产生错误3.9 内建函数FreeMarker还提供了一些内建函数来转换输出,可以在任何变量后紧跟?,?后紧跟内建函数,就可以通过内建函数来轮换输出变量.下面是常用的内建的字符串函数:html:对字符串进行HTML编码cap_first:使字符串第一个字母大写lower_case:将字符串转换成小写upper_case:将字符串转换成大写trim:去掉字符串前后的空白字符下面是集合的常用内建函数size:获取序列中元素的个数下面是数字值的常用内建函数int:取得数字的整数部分,结果带符号例如:<#assign test="Tom & Jerry">${test?html}${test?upper_case?html}结果是:Tom & Jerry TOM & JERRY3.10 空值处理运算符FreeMarker对空值的处理非常严格,FreeMarker的变量必须有值,没有被赋值的变量就会抛出异常,因为FreeMarker未赋值的变量强制出错可以杜绝很多潜在的错误,如缺失潜在的变量命名,或者其他变量错误.这里所说的空值,实际上也包括那些并不存在的变量,对于一个Java的null值而言,我们认为这个变量是存在的,只是它的值为null,但对于FreeMarker模板而言,它无法理解null值,null值和不存在的变量完全相同.为了处理缺失变量,FreeMarker提供了两个运算符:!:指定缺失变量的默认值??:判断某个变量是否存在其中,!运算符的用法有如下两种:variable!或variable!defaultValue,第一种用法不给缺失的变量指定默认值,表明默认值是空字符串,长度为0的集合,或者长度为0的Map对象.使用!指定默认值时,并不要求默认值的类型和变量类型相同.使用??运算符非常简单,它总是返回一个布尔值,用法为:variable??,如果该变量存在,返回true,否则返回false3.11 运算符的优先级FreeMarker中的运算符优先级如下(由高到低排列):1,一元运算符:!2,内建函数:?3,乘除法:*, / , %4,加减法:- , +5,比较:> , < , >= , <= (lt , lte , gt , gte)6,相等:== , = , !=7,逻辑与:&&8,逻辑或:||9,数字范围:..实际上,我们在开发过程中应该使用括号来严格区分,这样的可读性好,出错少4 FreeMarker的常用指令FreeMarker的FTL指令也是模板的重要组成部分,这些指令可实现对数据模型所包含数据的抚今迭代,分支控制.除此之外,还有一些重要的功能,也是通过FTL指令来实现的.4.1 if指令这是一个典型的分支控制指令,该指令的作用完全类似于Java语言中的if,if指令的语法格式如下:<#if condition>...<#elseif condition>...<#elseif condition>...<#else> ...</#if>例子如下:<#assign age=23><#if (age>60)>老年人<#elseif (age>40)>中年人<#elseif (age>20)>青年人<#else> 少年人</#if>输出结果是:青年人上面的代码中的逻辑表达式用括号括起来主要是因为里面有>符号,由于FreeMarker会将>符号当成标签的结束字符,可能导致程序出错,为了避免这种情况,我们应该在凡是出现这些符号的地方都使用括号.4.2 switch , case , default , break指令这些指令显然是分支指令,作用类似于Java的switch语句,switch指令的语法结构如下:<#switch value><#case refValue>...<#break><#case refValue>...<#break><#default>...</#switch>4.3 list, break指令list指令是一个迭代输出指令,用于迭代输出数据模型中的集合,list指令的语法格式如下:<#list sequence as item>...</#list>上面的语法格式中,sequence就是一个集合对象,也可以是一个表达式,但该表达式将返回一个集合对象,而item是一个任意的名字,就是被迭代输出的集合元素.此外,迭代集合对象时,还包含两个特殊的循环变量:item_index:当前变量的索引值item_has_next:是否存在下一个对象也可以使用<#break>指令跳出迭代例子如下:<#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as x>${x_index + 1}.${x}<#if x_has_next>,</if><#if x="星期四"><#break></#if></#list>4.4 include指令include指令的作用类似于JSP的包含指令,用于包含指定页.include指令的语法格式如下:<#include filename [options]>在上面的语法格式中,两个参数的解释如下:filename:该参数指定被包含的模板文件options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,其中encoding 指定包含页面时所用的解码集,而parse指定被包含文件是否作为FTL文件来解析,如果省略了parse选项值,则该选项默认是true.4.5 import指令该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import 指令的语法格式如下:<#import "/lib/common.ftl" as com>上面的代码将导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中.4.6 noparse指令noparse指令指定FreeMarker不处理该指定里包含的内容,该指令的语法格式如下:<#noparse>...</#noparse>看如下的例子:<#noparse><#list books as book><tr><td>${}<td>作者:${book.author}</#list></#noparse>输出如下:<#list books as book><tr><td>${}<td>作者:${book.author}</#list>4.7 escape , noescape指令escape指令导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响到body内出现的插值,使用escape指令的语法格式如下:<#escape identifier as expression>...<#noescape>...</#noescape></#escape>看如下的代码:<#escape x as x?html>First name:${firstName}Last name:${lastName}Maiden name:${maidenName}</#escape>上面的代码等同于:First name:${firstName?html}Last name:${lastName?html}Maiden name:${maidenName?html}escape指令在解析模板时起作用而不是在运行时起作用,除此之外,escape指令也嵌套使用,子escape继承父escape的规则,如下例子:<#escape x as x?html>Customer Name:${customerName}Items to ship;<#escape x as itemCodeToNameMap[x]>${itemCode1}${itemCode2}${itemCode3}${itemCode4}</#escape></#escape>上面的代码类似于:Customer Name:${customerName?html}Items to ship;${itemCodeToNameMap[itemCode1]?html}${itemCodeToNameMap[itemCode2]?html}${itemCodeToNameMap[itemCode3]?html}${itemCodeToNameMap[itemCode4]?html}对于放在escape指令中所有的插值而言,这此插值将被自动加上escape表达式,如果需要指定escape指令中某些插值无需添加escape表达式,则应该使用noescape指令,放在noescape 指令中的插值将不会添加escape表达式.4.8 assign指令assign指令在前面已经使用了多次,它用于为该模板页面创建或替换一个顶层变量,assign指令的用法有多种,包含创建或替换一个顶层变量, 或者创建或替换多个变量等,它的最简单的语法如下:<#assign name=value [in namespacehash]>,这个用法用于指定一个名为name的变量,该变量的值为value,此外,FreeMarker允许在使用assign指令里增加in子句,in子句用于将创建的name变量放入namespacehash命名空间中.assign指令还有如下用法:<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>,这个语法可以同时创建或替换多个顶层变量,此外,还有一种复杂的用法,如果需要创建或替换的变量值是一个复杂的表达式,则可以使用如下语法格式:<#assign name [in namespacehash]>capture this</#assign>,在这个语法中,是指将assign指令的内容赋值给name变量.如下例子:<#assign x><#list ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as n>${n}</#list></#assign>${x}上面的代码将产生如下输出:星期一星期二星期三星期四星期五星期六星期天虽然assign指定了这种复杂变量值的用法,但是我们也不要滥用这种用法,如下例子:<#assign x>Hello ${user}!</#assign>,以上代码改为如下写法更合适:<#assign x="Hello ${user}!">4.9 setting指令该指令用于设置FreeMarker的运行环境,该指令的语法格式如下:<#setting name=value>,在这个格式中,name的取值范围包含如下几个:locale:该选项指定该模板所用的国家/语言选项number_format:指定格式化输出数字的格式boolean_format:指定两个布尔值的语法格式,默认值是true,falsedate_format,time_format,datetime_format:指定格式化输出日期的格式time_zone:设置格式化输出日期时所使用的时区4.10 macro , nested , return指令macro可以用于实现自定义指令,通过使用自定义指令,可以将一段模板片段定义成一个用户指令,使用macro指令的语法格式如下:<#macro name param1 param2 ... paramN>...<#nested loopvar1, loopvar2, ..., loopvarN>...<#return>...</#macro>在上面的格式片段中,包含了如下几个部分:name:name属性指定的是该自定义指令的名字,使用自定义指令时可以传入多个参数paramX:该属性就是指定使用自定义指令时报参数,使用该自定义指令时,必须为这些参数传入值nested指令:nested标签输出使用自定义指令时的中间部分nested指令中的循环变量:这此循环变量将由macro定义部分指定,传给使用标签的模板return指令:该指令可用于随时结束该自定义指令.看如下的例子:<#macro book> //定义一个自定义指令j2ee</#macro><@book /> //使用刚才定义的指令上面的代码输出结果为:j2ee在上面的代码中,可能很难看出自定义标签的用处,因为我们定义的book指令所包含的内容非常简单,实际上,自定义标签可包含非常多的内容,从而可以实现更好的代码复用.此外,还可以在定义自定义指令时,为自定义指令指定参数,看如下代码:<#macro book booklist> //定义一个自定义指令booklist是参数<#list booklist as book>${book}</#list></#macro><@book booklist=["spring","j2ee"] /> //使用刚刚定义的指令上面的代码为book指令传入了一个参数值,上面的代码的输出结果为:spring j2ee不仅如此,还可以在自定义指令时使用nested指令来输出自定义指令的中间部分,看如下例子:<#macro page title><html><head><title>FreeMarker示例页面- ${title?html}</title></head><body><h1>${title?html}</h1><#nested> //用于引入用户自定义指令的标签体</body></html></#macro>上面的代码将一个HTML页面模板定义成一个page指令,则可以在其他页面中如此page指令:<#import "/common.ftl" as com> //假设上面的模板页面名为common.ftl,导入页面<@com.page title="book list"><u1><li>spring</li><li>j2ee</li></ul></@com.page>从上面的例子可以看出,使用macro和nested指令可以非常容易地实现页面装饰效果,此外,还可以在使用nested指令时,指定一个或多个循环变量,看如下代码:<#macro book><#nested 1> //使用book指令时指定了一个循环变量值<#nested 2></#macro><@book ;x> ${x} .图书</@book>当使用nested指令传入变量值时,在使用该自定义指令时,就需要使用一个占位符(如book指令后的;x).上面的代码输出文本如下:1 .图书2 .图书在nested指令中使用循环变量时,可以使用多个循环变量,看如下代码:<#macro repeat count><#list 1..count as x> //使用nested指令时指定了三个循环变量<#nested x, x/2, x==count></#list></#macro><@repeat count=4 ; c halfc last>${c}. ${halfc}<#if last> Last! </#if></@repeat>上面的输出结果为:1. 0.52. 13. 1.54. 2 Last;return指令用于结束macro指令,一旦在macro指令中执行了return指令,则FreeMarker不会继续处理macro指令里的内容,看如下代码:<#macro book>spring<#return>j2ee</#macro><@book />上面的代码输出:spring,而j2ee位于return指令之后,不会输出.FreeMarker是一个非常优秀的模板引擎,这个模板引擎可用于任何场景, FreeMarker负责将数据模型中的数据合并到模板中,从而生成标准输出.界面开发人员只需要关于界面(也就是模板文件)的开发,而业务逻辑开发者只需要负责将需要显示的数据填入数据模型-----FreeMarker负责合并数据模型和模板,从而生成标准输出.FreeMarker特别适应于MVC模式的Web应用,虽然FreeMarker具有一些编程能力,但这种编程能力非常有限,无法实现业务逻辑, 只能提供一些数据格式的转换功能.因此,通常由Java程序准备要显示的数据,由FreeMarker模板引擎来生成页面,而FreeMarker模板则提供页面布局支持.此外,FreeMarker也是与Web容器无关的,也就是FreeMarker并不一定需要运行在Web容器中:FreeMarker同样可以应用于非Web应用程序环境.而且,FreeMarker并不是只能生成HTML 页面,它也可以生成各种文本,如XML,RTF,Java源代码等.Struts2默认采用FreeMarker作为其模板文件,而Struts2所有的主题模板文件都是采用FreeMarker编写的,eclipse中的JSP,Java等模板文件也是采用FreeMarker技术.1,在java程序中使用FreeMarkerFreeMarker的模板就是一个.ftl文本文件,在该文件中使用了一些FreeMarker的特别标记,这些标记会动态显示,或者控制程序输出,如下面的模板文件代码:${name},你好!${msg}这里类似于${}的就是动态的内容,称作"插值".为了使用FreeMarker来将数据模型中的值合并到模板文件中,可按如下步骤进行:1,创建Configuration实例,该实例负责管理FreeMarker的模板加载路径,负责生成模板实例2,使用Configuration实例来生成Template实例,同进需要指定使用的模板文件3,填充数据模型,数据模型就是一个Map对象4,调用Template实例的process方法完成合并.下面是一个使用FreeMarker创建输出的Java程序,程序源代码如下:package lee;import java.util.*;import java.io.*;import freemarker.template.*;public class HelloFreeMarker{private Configuration cfg;public void init() throws Exception{//初始化FreeMarker配置//创建一个Configuration实例cfg = new Configuration();//设置FreeMarker的模版文件位置cfg.setDirectoryForTemplateLoading(new File("templates"));}public void process()throws Exception{Map root = new HashMap();root.put("name", "FreeMarker!");root.put("msg" , "您已经完成了第一个FreeMarker的示例");Template t = cfg.getTemplate("test.ftl");t.process(root, new OutputStreamWriter(System.out));}public static void main(String[] args)throws Exception{。
FreeMarker模版语言讲解1.FreeMarker的简单介绍。
FreeMarker是一个模板引擎,一个基于模板生成文本输出的通用工具,使用纯Java编写。
FreeMarker我们的第一印象是用来替代JSP的,但是与JSP 不同的是FreeMarker 模板可以在 Servlet容器之外使用。
可以使用它们来生成电子邮件、配置文件、 XML 映射等。
或者直接生成HTML。
虽然FreeMarker具有一些编程的能力,但通常由Java程序准备要显示的数据,由FreeMarker生成页面,通过模板显示准备的数据(如下图)2.FreeMarker 入门。
支持的数据类型:字符串、数字、布尔、日期容器:JSON、集合(数组)2.1.View(FreeMarker)渲染的全过程。
2.2.第一个简单的FreeMarker 尝试。
FreeMarker代码2.3.第二个简单的FreeMarker 尝试,Servlet Web方式展现。
FreeMarker代码3.FreeMarker 语法介绍。
Freemarker 基本语法是EL表达式,写法和在JSP里写法一致${},自身的语法是以<#tag>...</#tag>方式,也可以[#tag]方式。
以“?”作为自身方法调用,以“.”作为属性调用,下面我们来全面的介绍下。
3.1.FreeMarker注释。
每个View层都是有自己的注释方式,这个地方提到的注释不同于HTML的注释方式。
HTML注释方式在页面查看源码是看的到的。
而FreeMarker ,JSP等模版语言的注释都是查看页面源码看不见的。
其实建议我们在写代码的时候采用各种模版自身的注释方式来写注释,这样可以达到业务安全的效果。
3.2.自带空字符串(对象)处理。
从JSP等其他View层使用过的童鞋们,在使用FreeMarker的时候,都会遇到一个问题,当一个值或者对象为null的时候,如果这个时候去使用就会抛出异常。
freemarkerftl模板_Web开发必会的模板引擎技术之Freemarker曾⼏何时,Web开发是个多么⾼⼤上的名字,程序猿们都以能搞定Web技术为荣,此时还没有前后端之说。
然⽽时过境迁,今⾮昔⽐,随着互联⽹的发展,社会分⼯进⼀步细化,职业岗位也更加细分。
慢慢开始就有了前端攻城狮和后端攻城狮。
技术也进⼀步细分,出现了以HTML、JS等为主的页⾯技术,以Java、Pyton为主的后端开发语⾔技术。
事实上,直到前后端分离开发模式已经逐渐成为主流的今天,前后端技术的划分也没能完全清晰。
我们可能会经常听到⼀个叫全栈⼯程师的名字,这是⼀类野⼼极其⼤,想前后端通吃程序猿。
这是要逼着其他程序猿回家种地的节奏哇。
⼤家都是程序猿,本⾃同根⽣,相煎何太急其实全栈⼯程师它本⾝就是真实的存在,听起来这好像是个病句,那我好好跟⼤家解释⼀下, 全栈⼯程师其实就是前端和后端技术都会的⼀类⼈,⽽这类⼈基本都是后端⼯程师。
为什么这么说呢,以Java⼯程师为例,哪个Java⼯程师不会HTML、JS呢,否则会被⼈鄙视的。
甚⾄经验丰富的⽼司机⽐真正前端⼯程师还要精通。
Web开发本⾝就是后端⼯程师的⼀部分⼯作。
⽐如,在Java Web开发领域程序猿通常是既写前端代码,也写后端代码。
⽽且Web开发有着很多很优秀的页⾯技术HTML、JSP等。
这些优秀的页⾯技术,使Java在Web开发领域有着举⾜轻重的地位。
咱们今天要学习的也是⼀个在Java开发领域⾮常流⾏的页⾯技术模板引擎技术-Freemarker。
⽤过Spring Boot的同学可能都知道,Spring Boot在⾃⼰体系⾥⾯默认⽀持的页⾯技术不是JSP,⽽是Thymleaf、Freemarker的模板引擎技术。
所以,今天咱们就来⼀起先来学习⼀下其中的⼀个,使⽤Freemarker模板引擎技术做Web开发。
那么问题来了,咱们⼀直在说模板引擎技术,那什么是模板引擎呢?接下来咱么先来了解⼀下模板引擎技术。
开源模板引擎Freemarker简述经济全球化、一体化给人们带来机遇的同时也带来了挑战,新技术、新理念层出不穷,企业之间的竞争也日趋激励。
随着JSP技术的产生和发展,改变了HTML技术仅提供静态页面的历史,使得人们可以有更佳的用户体验和更高的参与程度[1]。
但是Web项目数量繁多、种类多样、更新频繁的特点,也给其设计、使用带来一定困难。
Freemarker是一个基于Java的开源模板引擎,它可以实现数据显示与数据模型的分离。
通过Freemarker可以方便、快捷的划分MVC设计模式中的模型层与视图层。
本文给出交通地理信息系统中集成Freemarker技术的具体步骤,并对其实际应用中的不足加以改进。
一、交通地理信息系统地理信息系统(GIS,Geographic Information System)是通过计算机硬件、软件技术,对地表空间地理数据进行处理的技术系统;而交通地理信息系统(GIS-T,Geography Information System -Transportation),则是GIS在交通领域的具体应用[2]。
在GIS-T中,服务器端需要对地理数据进行采集、存储、管理、分析和运算,浏览器端则需要对以上数据进行显示和描述。
为了减少开发难度,可以通过Freemarker将业务逻辑代码和交互显示代码分离。
本文以GIS-T注册模块为例阐述Freemarker模板引擎的应用。
好的注册系统可以给用户带来更佳的体验,是Web项目成功的第一步。
二、开源模板引擎Freemarker简介开源模板引擎Freemarker由于功能强大、方便简单、可读性好在Web项目中被广泛使用[3]。
Freemarker具有强大的模板语言,通用的数据模型,Web开发支持,可国际化或本地化,以及强大的XML编程能力[4]。
Freemarker的目标是可生成任何格式的文本,方便的嵌入到Web项目中,可插入的模板载入器,并用生成的文本做任何想做的事情(存储,E-mail,信息反馈等)。
freemarker的使⽤⼀:freemarker是什么?freemarker是⼀个模板引擎,基于定义的模板和数据⽣成对应的⽂本(HTML,xml,java等),是⼀个⽣成⽂本的⼯具。
⼆:freemarker的使⽤⽅法(1)在⼯程中引⼊freemarker相关的依赖<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency>View Code(2)使⽤的步骤第⼀步:创建⼀个Configuration对象,直接new⼀个即可,构造参数是freemarker的版本号第⼆步:设置模板⽂件所在的路径,需要给出在磁盘上储存的全路径第三步:设置⽣成的⽂件的编码格式,⼀般为utf-8格式第四步:加载模板,创建模板对象第五步:创建模板使⽤的数据集,可以使pojo也可以是map类型的第六步:创建Write流对象,将⽂件⽂件输出,需要指定⽣成的⽂件的名称第七步:调⽤模板的process⽅法,⽣成相应的⽂本第⼋步:关闭流@Testpublic void genFile() throws Exception {// 第⼀步:创建⼀个Configuration对象,直接new⼀个对象。
构造⽅法的参数就是freemarker对于的版本号。
Configuration configuration = new Configuration(Configuration.getVersion());// 第⼆步:设置模板⽂件所在的路径。
configuration.setDirectoryForTemplateLoading(new File("D:/workspace/item-web/src/main/webapp/WEB-INF/ftl"));// 第三步:设置模板⽂件使⽤的字符集。
freemarker1⼀些内建函数和⽤法${" green mouse"?cap_first} --> Green mouse //字符串中的第⼀个单词的⾸字母⼤写${"ABCDF"?lower_case} --> abcdf //字符串⼩写形式[${"a"?left_pad(5)}] --> [ a] //距左边如果它仅仅⽤1个参数,将在字符串的开始插⼊空⽩,知道整个串的长度达到参数指定的值. 如果字符串长度达到或者超过指定的长度,就什么都不做.[${"a"?left_pad(8,".oO")}] -->[.oO.oO.a]//第⼆个参数也可以是长度⽐1⼤的字符串,这个字符串会周期性的插⼊.<#if "piceous"?contains("ice")>It contains "ice"<#/if> --> It contains "ice" //contains 包含${"aaaaa"?repalce("aaa","XX")} --> XXaa //在元字符串中,⽤另外⼀个字符串来替换原字符串中出现它的部分不处理词的边界<#assign x= 's/b c'> ${x?url} --> a%2Fb%20c //通常引⽤的属性值,⽤普通引号("")包括,⽽不是单引号(''),因为单引号是不被URL转义的,<#list "someMOOtestMOOtext"?split("MOO" as x)>-${x}</#list> --> -some -test - text //split 分割,(${" green mouse "}?trim) --> (green mouse) //trim 去掉字符串⾸尾的空格<替换为<>替换为>&替换为&"替换为"'替换为'学习是枯燥的.。
freemarker 语法完整版2010/08/04 0 freemarker 语法完整版最常用的概念1、scalars:存储单值字符串:简单文本由单或双引号括起来。
数字:直接使用数值。
日期:通常从数据模型获得布尔值:true 或false,通常在#if 标记中使用2、hashes:充当其它对象的容器,每个都关联一个唯一的查询名字具有一个唯一的查询名字和他包含的每个变量相关联。
3、sequences:充当其它对象的容器,按次序访问使用数字和他包含的每个变量相关联。
索引值从0 开始。
4、集合变量:除了无法访问它的大小和不能使用索引来获得它的子变量:集合可以看作只能由#list... 指令使用的受限sequences。
5、方法:通过传递的参数进行计算,以新对象返回结果方法变量通常是基于给出的参数计算值在数据模型中定义。
6、用户自定义FTL 指令:宏和变换器7、节点节点变量表示为树型结构中的一个节点,通常在XML 处理中使用。
在模板里对sequences 和hashes 初始化sequences1. [ you , me , he ]2. 1..1003. [ { Akey : Avalue },{ Akey1 : Avalue1 }, { Bkey : Bvalue },{ Bkey1 : Bvalue1 }, ] hashes { you : a , me : b , he : c }注释标志#--这里是注释-- 旧版本的freemarker 采用的是#comment 注释/#comment 方法sequences 内置方法sequence?first 返回sequence 的第一个值;前提条件sequence 不能是nullsequence?last 返回sequence 最后一个值sequence?reverse 反转sequence 的值sequence?size 返回sequence 的大小sequence?sort 对sequence 按里面的对象toString()的结果进行排序sequence?sort_by(value)对sequence 按里面的对象的属性。
freemarker的标签语法一、Freemarker是个啥? 。
咱先来说说Freemarker是个啥玩意儿。
Freemarker呢,就像是一个超级厉害的小助手,专门用来处理模板的。
你可以把它想象成一个魔法盒,你给它一些数据,再给它一个模板,它就能按照这个模板把数据变成超级酷炫的东西,像网页啦、邮件内容啦之类的。
为啥要用Freemarker呢?你想啊,要是你每次做网页或者写邮件都要从头开始写代码,那得多累啊。
有了Freemarker,你就可以把那些经常用到的部分做成模板,然后只要把不同的数据塞进去就好了,就像搭积木一样简单又有趣。
二、基本标签语法来咯 。
(一)插值表达式。
这可是Freemarker的基础操作哦。
插值表达式就像一个小嘴巴,它会把数据“说”出来。
在Freemarker里,插值表达式的格式是`{变量名}`。
比如说,你有一个变量叫`userName`,里面存着用户的名字,那你在模板里写 `{userName}`,Freemarker就会把这个变量的值显示出来。
是不是很神奇呢?就像你告诉它一个小秘密,然后它就会把这个秘密展示给大家看。
(二)指令标签。
1. if指令。
这个 `if` 指令就和我们在编程里常见的 `if` 语句差不多啦。
比如说,你想根据用户的年龄来显示不同的内容。
你可以这样写:<#if age > 18>.欢迎,你已经成年啦!<#else>.小宝贝,你还未成年呢。
</#if>.这里的 `age` 就是我们的变量,根据它的值,Freemarker就会决定显示哪一段内容。
这就像是Freemarker在做选择题一样,根据不同的情况选择不同的答案。
2. list指令。
当你有一组数据,比如说一个用户的购物清单,你就可以用 `list` 指令来遍历它。
像这样:<#list shoppingList as item>.- {item}这里的 `shoppingList` 是一个列表类型的变量,`item` 呢,就是每次遍历出来的一个元素。
一、准备工作1.1 下载文件可以从htt p://freema rker.source forg/站点下载最新的(最新版本是0.9.14)。
free marke r.jar包(目前最新版本是2.3.18)与eclip se插件1.2 安装ecli pse插件将下载来的e clips e插件解压缩到本地磁盘,更改huds on.freema rker_ide_0.9.14文件夹中的free marke r-2.3.6.jar文件更改成最新版本的fre emark er-2.3.18.jar,并且将MET A-INF/MANIFE ST.MF文件中的Bundl e-ClassP ath属性值修改为f reema rker-2.3.18.jar。
最后将hud son.freema rker_ide_0.9.14放到ec lipse的plug ins目录中,完成ecli pse 插件的安装。
1.3 freema rker文档下载从http://freema rker.source forg/官方网站中下载帮助文档(也有中文的手册)二、freema rker的使用2.1 简介2.1.1 FTL tag标签由于free marke r tag标签是属于fre emark er的指令,它们仅仅是f reema rker处理过程中的信息,而不会输出到页面上,所以它们与h tml标签有一些区别。
这些标签都是以#号开头,如<#import"/public/work_p ublic.ftl" as public>。
但用户自定义的标签是以@符号开头,如在free marke r中使用s truts标签:<@s.if test="result s!=null&&result s.size()!=0">注意FTL标签不可以在其他FTL标签和插值中使用(注释可以在F TL标签和插值中使用,因为它在解析时,整个注释都将抛弃,不会影响具体代码),如下面这样就是一个错误的写法:<#if <#includ e 'foo'>='bar'>...</#if>2.1.2 注释freema rker的文档注释与html相似,但它是以<#--和-->来分割的。