freemarker中文手册
ftl编辑器(freemarker)的使用和说明

一、准备工作1.1 下载文件可以从/站点下载最新的freemarker.jar包(目前最新版本是2.3.18)与eclipse插件(最新版本是0.9.14)。
1.2 安装eclipse插件将下载来的eclipse插件解压缩到本地磁盘,更改hudson.freemarker_ide_0.9.14文件夹中的freemarker-2.3.6.jar文件更改成最新版本的freemarker-2.3.18.jar,并且将META-INF/MANIFEST.MF文件中的Bundle-ClassPath属性值修改为freemarker-2.3.18.jar。
最后将hudson.freemarker_ide_0.9.14放到eclipse的plugins目录中,完成eclipse 插件的安装。
1.3 freemarker文档下载从/官方网站中下载帮助文档(也有中文的手册)二、freemarker的使用2.1 简介2.1.1 FTL tag标签由于freemarker tag标签是属于freemarker的指令,它们仅仅是freemarker 处理过程中的信息,而不会输出到页面上,所以它们与html标签有一些区别。
这些标签都是以#号开头,如<#import "/public/work_public.ftl" as public>。
但用户自定义的标签是以@符号开头,如在freemarker中使用struts标签:<@s.if test="results!=null&&results.size()!=0">注意FTL标签不可以在其他FTL标签和插值中使用(注释可以在FTL标签和插值中使用,因为它在解析时,整个注释都将抛弃,不会影响具体代码),如下面这样就是一个错误的写法:<#if <#include 'foo'>='bar'>...</#if>2.1.2 注释freemarker的文档注释与html相似,但它是以<#--和-->来分割的。
freemaeker全面教程

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指令之后,不会输出.if, else, elseifswitch, case, default, breaklist, breakincludeImportcompressescape, noescapeassignglobalsettingmacro, nested, returnt, lt, rt3一些常用方法或注意事项表达式转换类数字循环对浮点取整数给变量默认值判断对象是不是null常用格式化日期添加全局共享变量数据模型直接调用java对象的方法字符串处理(内置方法)在模板里对sequences和hashes初始化注释标志sequences内置方法hashes内置方法4 freemarker在web开发中注意事项web中常用的几个对象view中值的搜索顺序在模板里ftl里使用标签如何初始化共享变量与webwork整合配置5高级方法自定义方法自定义 Transforms1概念最常用的3个概念sequence 序列,对应java里的list、数组等非键值对的集合hash 键值对的集合namespace 对一个ftl文件的引用,利用这个名字可以访问到该ftl文件的资源2指令if, else, elseif语法<#if condition>...<#elseif condition2>...<#elseif condition3>......<#else>...</#if>用例<#if x = 1>x is 1</#if><#if x = 1>x is 1<#else>x is not 1</#if>switch, case, default, break语法<#switch value><#case refValue1>...<#break><#case refValue2>...<#break>...<#case refValueN>...<#break><#default>...</#switch>用例字符串<#switch being.size><#case "small">This will be processed if it is small <#break><#case "medium">This will be processed if it is medium <#break><#case "large">This will be processed if it is large <#break><#default>This will be processed if it is neither </#switch>数字<#switch x><#case x = 1>1<#case x = 2>2<#default>d</#switch>如果x=1 输出 1 2, x=2输出 2, x=3 输出dlist, break语法<#list sequence as item>...<#if item = "spring"><#break></#if>...</#list>关键字item_index:是list当前值的下标item_has_next:判断list是否还有值用例<#assign seq = ["winter", "spring", "summer", "autumn"]><#list seq as x>${x_index + 1}. ${x}<#if x_has_next>,</#if></#list>输出1. winter,2. spring,3. summer,4. autumninclude语法<#include filename>or<#include filename options>options包含两个属性encoding=”GBK” 编码格式parse=true 是否作为ftl语法解析,默认是true,false就是以文本方式引入.注意在ftl文件里布尔值都是直接赋值的如parse=true,而不是parse=”true” 用例/common/copyright.ftl包含内容Copyright 2001-2002 ${me}<br>All rights reserved.模板文件<#assign me = "Juila Smith"><h1>Some test</h1><p>Yeah.<hr><#include "/common/copyright.ftl" encoding=”GBK”>输出结果<h1>Some test</h1><p>Yeah.<hr>Copyright 2001-2002 Juila SmithAll rights reserved.Import语法<#import path as hash>类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件。
freemarker常用指令

freemarker常用指令Freemarker常用指令一、概述Freemarker是一种Java模板引擎,常用于生成动态网页、电子邮件和其他文本格式。
它使用简单的模板语言来定义模板,并通过替换模板中的占位符来生成最终的文本输出。
本文将介绍Freemarker 常用指令,帮助读者更好地理解和使用Freemarker。
二、输出指令1. #-- 输出文本 --#这是Freemarker中最基本的输出指令,用于直接输出文本内容。
例如:#-- 这是一段文本 --#。
2. ${expression}这是Freemarker中最常用的输出指令,用于输出表达式的值。
表达式可以是变量、方法调用或其他Freemarker支持的表达式。
例如:${name}表示输出变量name的值。
3. #if-#else-#elseif-#end这是Freemarker中的条件判断指令,用于根据条件来输出不同的内容。
可以使用if、else if和else来定义多个条件分支。
例如:#if (score > 90)优秀#elseif (score > 80)良好#else需要努力4. #list-#items-#sep-#end这是Freemarker中的循环指令,用于遍历一个集合并输出其中的元素。
可以使用items定义要遍历的集合,使用sep定义元素之间的分隔符。
例如:#list users as user${}#sep,#end三、变量指令1. #assign这个指令用于定义一个局部变量,并为其赋值。
例如:#assign count = 10。
2. #global这个指令用于定义一个全局变量,并为其赋值。
全局变量可以在整个模板中使用。
例如:#global count = 10。
3. #local这个指令用于在指定的作用域中定义一个局部变量,并为其赋值。
作用域可以是当前模板、当前循环或当前条件分支。
例如:#local count = 10。
常用freemarker使用文档

常⽤freemarker使⽤⽂档设置价格格式<#setting number_format = "currency" /><#assign price = 42 />${price}-${price?string}--${price?string.number}---${price?string.currency}----${price?string.percent}-----输出结果:设置价格格式¥42.00- ¥42.00-- 42--- ¥42.00---- 4,200%-----设置⽇期格式<#assign lastUpdated = "2009-01-07 15:05"?datetime("yyyy-MM-dd HH:mm") />${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")};${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')'")};${lastUpdated?string.short};${lastUpdated?string.long};输出结果:2009-01-07 15:05:00 中国标准时间;2009-01-07 15:05:00 中国标准时间;星期三,⼀⽉ 7,09;星期三,⼀⽉ 07,2009,03:05:00 下午 (CST);09-1-7 下午3:05;2009年1⽉7⽇下午03时05分00秒;判断布尔<#assign foo=true />${foo?string("是foo","⾮foo")}输出结果:是foo集合<#assign mynums=[11,12,13,14,15,16,17,18,19]/><#list mynums as mn>${mn}<br></#list>输出结果:(¥是默认格式数字)¥12.00¥13.00¥14.00¥15.00¥16.00¥17.00¥18.00¥19.00拆分序列<#-- 这⾥是将mynums序列中下标从3到6之间的元素拆分出来,组成⼀个新的序列 --> <#assign mynum01=mynums[3..6]/><#list mynum01 as mn01>${mn01}</#list>输出结果:¥14.00¥15.00¥16.00¥17.00字符串的拆分(截取字符串)<br>${"你好,你来了吗今天看书了吗!"[0..8]}<br>你好,你来了吗今天...输出结果:你好,你来了吗今天你好,你来了吗今天...连续序列(即num01为完整集合不是拆分的)从55到58:注意此时若写成[55..58]或者[66..68]则会报错<#assign num01=55..58/><#list num01 as num>${num}</#list><#list 66..68 as num>${num}</#list>哈希表(Map)定义哈希表<#assign maps={"1":"张三","2":"李四"}>${maps["1"]}输出结果:张三<#--以下代码可以将map的key转换为相应的序列--><#assign keys=maps?keys><#list keys as key>${key}---${maps[key]}</#list>输出结果:1---张三2---李四<#assign users={"username":"张三","password":"123"}>${ername}---${users["password"]}输出结果:张三---123字符串操作a、字符串链接字符串连接有两种语法A、使⽤${..}(或#{..})在字符串常量部分插⼊表达式的值,从⽽完成字符串连接B、直接使⽤连接运算符(+)来连接字符串使⽤第⼀种语法来连接字符串${"Hello,${user}!"}第⼆种使⽤连接符号来连接字符串${"Hello,"+user+"!"};值的注意的是,${..}只能⽤于⽂本部分,因此,下⾯的代码是错误的:<#if ${isBig}>Wow!</#if><#if "${isBig}">Wow!</#if>应该写成:<#if isBig>Wow!</#if>集合连接运算符这⾥所说的集合连接运算时将两个集合连接成⼀个新的集合,连接集合的运算符是+,例如<#list ["星期⼀"," 星期⼆","星期三"]+["星期四","星期五"] as x>${x}</#list>Map连接运算符Map对象的连接运算也是将两个Map对象连接成⼀个新的Map对象,Map对象的连接运算符是+。
freemarker(ftl)模板开发常用方法(迭代,数值格式化等)

freemarker(ftl)模板开发常⽤⽅法(迭代,数值格式化等)1.if-else常⽤<#if signStatus??> //如果signStatus值存在 <#if signStatus=='2'>是<#else>否</#if> <#else> 否</#if>if-elseif-else1 <#if condition>2 ...3 <#elseif condition2>4 ...5 <#elseif condition3>6 ...7 ...8 <#else>9 ...10 </#if>2.时间格式化时间戳转⽇期 ${time?number_to_datetime} ${time?number*1000} 时间戳乘1000⽇期格式化 ${dateTime?string('yyyy-MM-dd hh:mm:ss')} 格式化为 2020-11-12 15:05:29 ${dateTime?string('yyyy-MM-dd ')} 格式化为 2020-11-123.数值格式化数值如果有⼩数保留两位⼩数,否则补0两位,例如128.81, 688则为 688.00${((totalInvoice.amount)!0)?string('###,##0.00')}特别需要注意的是 ?前⾯的数值需要括号()⽐如:${additionsTotalAmt!0?string('###,##0.00')}⽆效果,⽽正确的是 ${(additionsTotalAmt!0)?string('###,##0.00')}另外,1 ${num?string('0.00')}2如果⼩数点后不⾜两位,⽤ 0 代替34 ${num?string('#.##')}5如果⼩数点后多余两位,就只保留两位,否则输出实际值6输出为:1239765.4678 ${num?string(',###.00')}9输出为:1,239,765.4610整数部分每三位⽤ , 分割,并且保证⼩数点后保留两位,不⾜⽤ 0 代替1112 ${num?string(',###.##')}13输出为:1,239,765.4614整数部分每三位⽤ , 分割,并且⼩数点后多余两位就只保留两位,不⾜两位就取实际位数,可以不不包含⼩数点1516 ${num?string('000.00')}17输出为:012.7018整数部分如果不⾜三位(000),前⾯⽤0补齐,否则取实际的整数位1920 ${num?string('###.00')}21等价于22 ${num?string('#.00')}23输出为:12.70参考https:///qq_32534855/article/details/676317881 ${price?string.currency}23对price进⾏格式化,显⽰为货币格式。
Freemarker 内置函数 数字、字符串、日期格式化freemarker

Freemarker 内置函数数字、字符串、日期格式化freemarker一、Sequence的内置函数1. sequence?first 返回sequence的第一个值。
2. sequence?last 返回sequence的最后一个值。
3. sequence?reverse 将sequence的现有顺序反转,即倒序排序4. sequence?size 返回sequence的大小5. sequence?sort 将sequence中的对象转化为字符串后顺序排序6. sequence?sort_by(value) 按sequence中对象的属性value进行排序二、Hash的内置函数1. hash?keys 返回hash里的所有key,返回结果为sequence2. hash?values 返回hash里的所有value,返回结果为sequence例如:<#assign user={“name”:“hailang”, “sex”:“man”}><#assign keys=user?keys><#list keys as key>${key}=${user[key]}</#list>三、操作字符串函数1. substring(start,end)从一个字符串中截取子串start:截取子串开始的索引,start必须大于等于0,小于等于endend: 截取子串的长度,end必须大于等于0,小于等于字符串长度,如果省略该参数,默认为字符串长度。
例子:${…str‟?substring(0)},结果为str${…str‟?substring(1)},结果为tr${…str‟?substring(2)},结果为r${…str‟?substring(3)},结果为${…str‟?substring(0,0)},结果为${…str‟?substring(0,1)},结果为s${…str‟?substring(0,2)},结果为st${…str‟?substring(0,3)},结果为str2. cap_first 将字符串中的第一个单词的首字母变为大写。
freemarker中文手册文档

FreeMarkerFreeMarker JavaFreeMarker HTML Web MVC FreeMarker Java FreeMarkerFreeMarker Web WebFreeMarker HTTP Servlet FreeMarker WebFreeMarker Model2 Struts JSPFreeMarker1HTML XML RTF JavaServletEmail Web Web2include if/elseif/elseHTML3FreeMarker Java JavaJavaBean XML SQL4 WebWeb HTMLModel2 Web JSPJSPMVC5UNICODEUS6 XML<#recurse> <#visit> 2.3 XMLXMLFreeMarker (1)11 + =FreeMarker—— HTML WebWebHTML FreeMarker<html><head><title>Welcome!</title></head><body><h1>Welcome ${user}!</h1><p>Our latest product:<a href="${latestProduct.url}">${}</a>!</body></html>HTML ${…} FreeMarker FreeMarker Template user latestProduct.url data model(root)|+- user = "Big Joe"|+- latestProduct|+- url = "products/greenmouse.html"|+- name = "green mouse"latestProduct user url name url name latestProductFreeMarker <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(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"hashesscalarsscalarsscalars root “. animals.mouse.pricesequences 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].name3FreeMarker${…} interpolations FreeMarkerFTL FreeMarker HTML HTML # @<#-- --> <!-- -->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>${}<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>${}<#if being.size = "large"></b></#if><td>${being.price} Euros</#list></table>FreeMarker (3)31FTL FreeMarkerInterpolation ${ } #{ }FTL FreeMarker HTML #<#-- --><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>${} for ${being.price} Euros[BR]</#list>[BR]</ul>[BR]</body>[BR]</html>[BR]FTL list FTL List ${name} ${NAME}InterpolationFTL 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] ...2FreeMarker FTLFTL HTML<#directivename parameters></#directivename><#directivename parameters/>@ # <@mydirective>...</@mydirective>FTL <ul><#list animals as being><li>${} for ${being.price} Euros<#if use = "Big Joe">(except for you)</#list></#if><#-- WRONG! --></ul>FreeMarkerFreeMarker FTL <#list[BR]animals as[BR]being[BR]>[BR]${} for ${being.price} Euros[BR]</#list >< </3${"It's \"quoted\" andthis is a backslash: \\"}${'It\'s "quoted" andthis is a backslash: \\'}It's "quoted" andthis is a backslash: \It's "quoted" andthis is a backslash: \\" (u0022)\' (u0027)\\ (u005C)\n (u000A)\r Return (u000D)\t Tab (u0009)\b Backspace (u0008)\f Form feed (u000C)\l<\g>\a&\{{\x Code4 16 Unicoderaw \ { r ${r"${foo}"}${r"C:\foo\bar"}${foo}C:\foo\bar“.“1E30 “.58 +8 08 8.00true false<#list ["winter", "spring", "summer", "autumn"] as x>${x}</#list>winterspringsummerautumn[2 + 2, [1, 2, 3, 4], "whatnot"]2..5 [2, 3, 4, 5]5..2hash/{"name":"green mouse", "price":150}${variable} $ @ #(root)|+- book| || +- title = "Breeding green mouses"| || +- author| || +- name = "Julia Smith"| || +- info = "Biologist, 1923-1985, Canada"|+- test = "title"book["author"].namebook.author.["name"]book["author"]["name"][startIndex..endIndex] startIndex endIndexFreeMarker .variablenameInterpolation${..} #{..} ${"Hello ${user}!"}${"${user}${user}${user}${user}"}+${"Hello " + user + "!"}${user + user + user + user}${..}<#if ${isBig}>Wow!</#if><#if "${isBig}">Wow!</#if><#if isBig>Wow!</#if>user “Big Joe ${user[0]}${user[4]}${user[1..4]}BJig J+ <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user> - ${user}</#list>- Joe- Fred- Julia- Kate+ 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${x * x - 100}${x / 2}${12 % 10}x 5-752.52${3 * "5"} <#-- WRONG! -->+ ${3 + "5"}35int${(x/2)?int}${1.1?int}${1.999?int}${-1.1?int}${-1.999?int}x 5211-1-1= == !== != <#if 1 = "1">Freemarker "x" "x " "X"< <= > >=Freemarker > FTL > >= <#if (x > y)>lt lte gt gte < <= > >=&& 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>“? “.html HTMLcap_firstlower_caseupper_casetrimsizeint -1.9?int -1 test "Tom & Jerry"${test?html}${test?upper_case?html}Tom & JerryTOM & JERRY[subvarName] [subStringRange]. (methodParams) +expr -expr !?* / %+ -< > <= >= lt lte gt gte== = !=and &&or ||..4 InterpolationInterpolationInterpolation ${expr}Interpolation #{expr} #{expr; format}InterpolationInterpolation#setting string Interpolation <#setting number_format="currency"/><#assign answer=42/>${answer}${answer?string} <#-- the same as ${answer} -->${answer?string.number}${answer?string.currency}${answer?string.percent}$42.00$42.0042$42.004,200%#setting string Interpolation ${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')'")}2003-04-08 21:24:44 Pacific Daylight TimeTue, Apr 8, '03Tuesday, April 08, 2003, 09:24:44 PM (PDT)#settingstring Interpolation<#assign foo=true/>${foo?string("yes", "no")}yesInterpolation #{expr; format} format mX XMX X<#-- If the language is US English the output is: --><#assign x=2.582/><#assign y=4/>#{x; M2} <#-- 2.58 -->#{y; M2} <#-- 4 -->#{x; m1} <#-- 2.6 -->#{y; m1} <#-- 4.0 -->#{x; m1M2} <#-- 2.58 -->#{y; m1M2} <#-- 4.0 -->FreeMarker (4)41macro<#macro greet><font size="+2">Hello Joe!</font></#macro>@ FTL #<@greet></@greet><@greet/>macro<#macro greet person><font size="+2">Hello ${person}!</font></#macro><@greet person="Fred"/> and <@greet person="Batman"/><font size="+2">Hello Fred!</font>and <font size="+2">Hello Batman!</font>FTL<@greet person=Fred/>Fred person<#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="Fred" color="black" background="green"/><@greet person="Fred"/><#macro greet person color="black"><font size="+2" color="${color}">Hello ${person}!</font></#macro><@greet person="Fred"/><#nested><#macro border><table border=4 cellspacing=0 cellpadding=4><tr><td><#nested></tr></td></table></#macro><@border>The bordered text</@border><table border=4 cellspacing=0 cellpadding=4><tr><td> The bordered text</tr></td></table><#nested><#macro do_thrice><#nested><#nested><#nested></#macro><@do_thrice>Anything.</@do_thrice>Anything.Anything.Anything.FTL <@border><ul><@do_thrice><li><@greet person="Joe"/></@do_thrice></ul></@border><table border=4 cellspacing=0 cellpadding=4><tr><td> <ul><li><font size="+2">Hello Joe!</font><li><font size="+2">Hello Joe!</font><li><font size="+2">Hello Joe!</font></ul></tr></td></table><#macro repeat count><#local y = "test"><#list 1..count as x>${y} ${count}/${x}: <#nested></#list></#macro><@repeat count=3>${y?default("?")} ${x?default("?")} ${count?default("?")}</@repeat>test 3/1: ? ? ?test 3/2: ? ? ?test 3/3: ? ? ?nested <@…><#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.52. 13. 1.54. 2 Last!2plain include assignlocallistplain plain<#assign x = "plain">1. ${x} <#-- we see the plain var. here --><@test/>6. ${x} <#-- the value of plain var. was not changed --><#list ["loop"] as x>7. ${x} <#-- now the loop var. hides the plain var. --><#assign x = "plain2"> <#-- replace the plain var, hiding does not materhere -->8. ${x} <#-- it still hides the plain var. --></#list>9. ${x} <#-- the new value of plain var. --><#macro test>2. ${x} <#-- we still see the plain var. here --><#local x = "local">3. ${x} <#-- now the local var. hides it --><#list ["loop"] as x>4. ${x} <#-- now the loop var. hides the local var. --></#list>5. ${x} <#-- now we see the local var. again --></#macro>1. plain2. plain3. local4. loop5. local6. plain7. loop8. loop9. plain2<#list ["loop 1"] as x>${x}<#list ["loop 2"] as x>${x}<#list ["loop 3"] as x>${x}</#list>${x}</#list>${x}</#list>loop 1loop 2loop 3loop 2loop 1global user Big Joe<#assign user = "Joe Hider">${user} <#-- prints: Joe Hider -->${er} <#-- prints: Big Joe -->3lib/my_test.ftl<#macro copyright date><p>Copyright (C) ${date} Julia Smith. All rights reserved.<br>Email: ${mail}</p></#macro><#assign mail = "jsmith@">import Freemarker import<#import "/lib/my_test.ftl" as my><#assign mail="fred@"><@my.copyright date="1999-2002"/>${my.mail}${mail}<p>Copyright (C) 1999-2002 Julia Smith. All rights reserved.<br>Email: jsmith@</p>jsmith@fred@assign <#import "/lib/my_test.ftl" as my>${my.mail}<#assign mail="jsmith@" in my>${my.mail}jsmith@jsmith@<#macro copyright date><p>Copyright (C) ${date} ${user}. All rights reserved.</p></#macro><#assign mail = "${user}@">user Fred<#import "/lib/my_test.ftl" as my><@my.copyright date="1999-2002"/>${my.mail}<p>Copyright (C) 1999-2002 Fred. All rights reserved.</p> Fred@。
FreeMarker使用手册

FreeMarker思想模板在FreeMarker模板中可以包括下面三种特定部分:1.${..}:称为interpolations,FreeMarker会在输出时用实际值进行代替2.FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始)3.注释:包含在<#--和-->之间数据模型典型的数据模型是树型结构,可以任意复杂和深层次:(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"${animals.elephant.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"${animals[1].name}FreeMarker基本语法注释语句<#-- 注释语句-->If语句●语法:<#if condition><#else></#if>●例子:1.boolean对象<% request.setAttribute("flag",true); %><#if flag>flag的值是True<#else>flag的值是false</#if>输出的结果:flag的值是True2.String对象<% request.setAttribute("str",”string”); %><#if str == “string” >str的值是string<#else>str的值是${str}</#if>输出的结果:str的值是string3.Number对象<% request.setAttribute("number",20); %><#if number == 20 >number的值是20<#else>number的值是${number}</#if>输出的结果:number的值是20<#if number gt 20 >number的值是大于20<#else>number的值是${number}</#if>(gt代表>号) 或者这样写( <#if (number > 20) >)输出的结果:number的值是大于204.自定义对象<% Student student = new Student();student.setName(“张三”);student.setAge(20);request.setAttribute(“student”,student);%>首先判断Student对象是否为空,再次输出Student对象的属性值<#if student?exists>学生名称:${}学生年龄:${student.age}<#else>Student对象是空值</#if>5.Map 、List对象<%Map map = new HashMap<String,Student>();List list = new ArrayList();Student student = new Student();student.setName(“张三”);student.setAge(20);list.add(student);map.put(“student”,student);request.setAttribute(“list”,list);request.setAttribute(“map”,map);%>首先判断对象是否为空,再次输出对象的属性值<#if list?exists && list?size != 0><#list list as student>学生名称:${}学生年龄:${student.age}</#list><#else>List对象是空的</#list><#if map?exists && map?size != 0><#list map?keys as students>输出map中的key的值:${students}Map对象中key必须是String类型,别的类型不支持<@assign stu = map[students]><#list stu as student >学生名称:${}学生年龄:${student.age}</#list><#else>Map对象是空的</#if>list语句●语法:<#list list as list_value></#list>●例子:Map 、List对象<%Map map = new HashMap<String,Student>();List list = new ArrayList();Student student = new Student();student.setName(“张三”);student.setAge(20);list.add(student);map.put(“student”,student);request.setAttribute(“list”,list);request.setAttribute(“map”,map);%>首先判断对象是否为空,再次输出对象的属性值<#if list?exists && list?size != 0><#list list as student>学生名称:${}学生年龄:${student.age}</#list><#else>List对象是空的</#list><#if map?exists && map?size != 0><#list map?keys as students>students_index:当前变量的索引值students_has_next: 是否存在下一个对象也可以使用<#break>指令跳出迭代输出map中的key的值:${students}Map对象中key必须是String类型,别的类型不支持<@assign stu = map[students]><#list stu as student >学生名称:${}学生年龄:${student.age}</#list><#else>Map对象是空的</#if><#list [“星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期天"] as days> ${days_index}list的索引位置<#if days_has_next>判断是否有下个值</#if><#if days == “星期四”><#break></#if></#list>switch语句语法:<#switch value><#case refValue1>语句<#break><#case refValue2>语句<#break><#default>语句</#switch>●例子<#switch being.size><#case "small">This will be processed if it is small<#break><#case "medium">This will be processed if it is medium<#break><#case "large">This will be processed if it is large<#break><#default>This will be processed if it is neither</#switch>include语句●作用:类似于jsp的包含作用,用于包含指定页●语法:<#include filename[options]>filename:该参数指定被包含的模板文件options:该参数可以省略,指定包含时的选项,包含encoding和parse两个选项,其中encoding指定包含页面时所用的解码集,而parse指定被包含文件是否作为FTL文件来解析,省略默认True●例子:<#include “/html/index.html”> 、<#include “/template/one.ftl”>import语句●作用:用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中●语法:<#import “/lib/common.ftl” as com>说明:将导入/lib/common.ftl模板文件中的所有变量,将这些变量放置在一个名为com的Map对象中●例子:文件common.ftl中的内容:<#assign aa = “FreeMarKer”><#import “/lib/common.ftl” as com> ${com.aa}输出结果:FreeMarkernoparse语句●作用:指定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> 没有做处理setting语句●作用:用于设置FreeMarker的运行环境●语法:<#setting name = value> name的取值范围包含如下:locale:该选择指定该模板所用的国家/语言选择number_format:指定格式化输出数字的格式boolean_format:指定两个布尔值的语法格式,默认值是true,falsedate_fromat,time_format,datetimr_format:指定格式化输出日期的格式time_zone:设置格式化输出日期时所使用的时区url_escaping_charset:classic_compatible:●例子:<#setting locale = “en_US”><#setting number_format="0.##">${1.234}输出结果:1.23escape、noescape语句●作用:导致body区的插值都会被自动加上escape表达式,但不会影响字符串内的插值,只会影响body内出现的插值●语法:<#escape identitier as expression>….<#noescape>…..</#noescape></#escape>●例子:class User{private String name;pringvate String userName;private UserInfo userInfo;}Class UserInfo{private String idCardNo;private String telephone;private String mobile;private String email;private String address;private String resume;private Sex gendar;}Public enum Sex implements EnumI18n{MAIE(0,”el.enum.human.status.male”),FEMALE(1,”el.enum.human.status.female”),Private String i18n;Sex(String i18n){This.i18n = i18n;}Public String getI18n(){Return this.i18n;}}<#escape x as x?if_exists?html>用户名:${user?if_erName}<br>姓名:${'name'}<br><#escape xx as user?if_erInfo?if_exists[xx]><#noescape>性别:<#if user?if_erInfo?if_exists.gendar?if_exists.i18n?exists>${action.getText(erInfo.gendar.i18n)}</#if></#noescape>身份证:${'idCardNo'}<br>联系电话:${'telephone'}<br>手机:${'mobile'}<br>邮箱:${'email'}<br>地址:${'address'}<br>个人简介:${'resume'}<br></#escape></#escape>assign语句作用:为模板创建和替换顶层变量●语法:1. <#assign name=value [in namespacehash]>2. :<#assign name1=value1 name2=value2 ... nameN=valueN [in namespacehash]>capture tHis</#assign>●例子:<#assign xx = “assign”>${xx} 输出assign<#assign s=JspTaglibs["/WEB-INF/struts-tags.tld"]><#assign bb ><#list ["free","marker","freemarker"] as aa>${aa}</#list></#assign>${bb}输出结果:free marker freemarkermacro,newsted,return语句●语法:<#macro name param1 param2 …..paramN>…….<#nested loopvar1,loopvar2,…,loopvarN>……<#return>….</macro>描述:name : 是macro变量的名字Param1 … paramN:macro变量保存参数值的名称,可以有默认的参数值●例子:<#-- create the macro variable →<#macro test>Test text</#marco><#-- call the macro: -→<@test/> 输出结果:Test tex<#-- Macro 带着参数→<#macro test foo bar baaz>Test text , and the params : ${foo},${bar}, ${baaz}</#macro><#-- call the macro: →<@test foo = “a” bar = “b” baaz = 5*5-2/>输出结果:Test text ,and the params : a, b, 23<#-- macro 参数带有默认值→<#macro test foo bar=”bar” baaz = -1>Test text,and the params: ${foo} ,${bar} ,${baaz}</#macro><@test foo = “a”/><@test foo = “a” bar=”b”/>输出结果:Test text , and the params : a ,Bar,-1Test text , and the params : a , b, -1一个更复杂的例子<#macro list title items><p>${title?cap_first}:<ul><#list items as x><li>${x?cap_first}</#list></ul></#macro><@list items=["mouse", "elephant", "python"] title="Animals"/> 输出结果:<p>Animals:<ul><li>Mouse<li>Elephant<li>Python</ul>A macro with support for a variable number of named parameters:<#macro img src extra...><img src="/context${src?html}"<#list extra?keys as attr>${attr}="${extra[attr]?html}"</#list>></#macro><@img src="/images/test.png" width=100 height=50 alt="Test"/>输出结果:<img src="/context/images/test.png" alt="Test"height="50"width="100">nested 例子<#macro do_thrice><#nested 1><#nested 2><#nested 3></#macro><@do_thrice ; x>${x} Anything.</@do_thrice>输出结果:1 Anything.2 Anything.3 Anything.一个复杂的nested例子<#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.52. 13. 1.54. 2 Last!一个macro带有return的例子<#macro test>Test text<#return>Will not be printed.</#macro><@test/>输出结果:Test textt,lt,rt语句●语法:<#t> 去掉一行前后空格和换行<#lt> 去掉一行左边的空格<#rt> 去掉右边的空格和换行<#nt> 取消去掉空格和换行的效果●例子:--1 <#t>2<#t>3<#lt>45<#rt>6--输出结果:--1 2345 6--compress语句●语法:<#compress> …. </#compress> ●作用:去掉多余的空格和空行●例子:<#assign x = " moo \n\n "> (<#compress>1 2 3 4 5${moo}test onlyI said, test only</#compress>)输出结果:(1 2 3 4 5mootest onlyI said, test only)global语法●语法<#global name=value>or<#global name1=value1 name2=value2 ... nameN=valueN>or<#global name>capture this</#global>●说明:全局赋值语法,利用这个语法给变量赋值,那么这个变量在所有的namespace中是可见的,如果这个变量被当前的assign语法覆盖如<#global x=2> <#assign x=1> 在当前页面里x=2将被隐藏,或者通过${.global.x}来访问FreeMarker内置函数substring()作用:取字串${“FreeMarker”?substring(0,2)} 输出结果:Fr作用:求字串在原串中的位置${“FreeMarker”?index_of(“ee”)) 输出结果:2cap_first作用:第一个字母大写${“freeMarker”?cap_first} 输出结果:FreeMarkeruncap_first作用:第一个字母不大写$(“FreeMarker”?uncap_first) 输出结果:freeMarkercaptitalize作用:单词之间的首字母大写例子:${“green mouse”?captitalize}输出结果:Green Mousechop_linebreakdate(),time(),datetime()作用:以某个时间格式,输出时间的值例子:<#assign date_val = “10/25/1995”?date(“MM/dd/yyyy”)><#assign time_val = “15:05:30”?time(“HH:mm:ss”)><#assign datatime_val = “1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")>输出结果:Oct 25, 19953:05:30 PMOct 25, 1995 3:05:00 PM作用:从字符串后面判断是否存在某个字符,返回true和false 例子:${“freemarker”?ends_with(“marker”)} true${“freemarker”?ends_with(“free”)} truehtmlgroupsj_string作用:在字符串引号前加”\”例子:<#assign beanName = …The “foo” bean.‟>${beanName?j_string} 输出结果:”The \”foo\” bean.”js_string作用:在字符串引号前加”\”例子:<#assign beanName = “The …foo‟ bean.”>${beanName?js_string} 输出结果:”The \‟foo\‟bean.”last_index_of()作用:求子串在原串最后出现的位置例子:${“freemarker”?last_index_of(“ar”)} 输出结果:5 length作用:字符串的长度例子:${“freemarker”?length} 输出结果:10lower_case作用:把大写字母转换成小写字母例子:${“FreeMARker”?lower_case} 输出结果:freemarke rleft_pad()注意:freemarker2.3以后的版本才出现作用:从左侧起填充字符例子:1.left_pad()只有一个参数时,默认空格填充,如果变量长度小于参数的长度填充空格,否则不填充[${""?left_pad(5)}][${"a"?left_pad(5)}][${"ab"?left_pad(5)}][${"abc"?left_pad(5)}][${"abcd"?left_pad(5)}][${"abcde"?left_pad(5)}][${"abcdef"?left_pad(5)}][${"abcdefg"?left_pad(5)}][${"abcdefgh"?left_pad(5)}]输出结果:[ ][ a][ ab][ abc][ abcd][abcde][abcdef][abcdefg][abcdefgh]2.如果left_pad()有两个参数,第一个参数是填充的数量,第二个参数是填充的字符[${""?left_pad(5, "-")}][${"a"?left_pad(5, "-")}][${"ab"?left_pad(5, "-")}][${"abc"?left_pad(5, "-")}][${"abcd"?left_pad(5, "-")}][${"abcde"?left_pad(5, "-")}]输出结果:[-----][----a][---ab][--abc][-abcd][abcde]right_pad()注意:freemarker2.3以后的版本才出现作用:从右侧填充字符串例子:参考left_pad() [${""?right_pad(5)}] [${"a"?right_pad(5)}] [${"ab"?right_pad(5)}] [${"abc"?right_pad(5)}] [${"abcd"?right_pad(5)}] [${"abcde"?right_pad(5)}] [${"abcdef"?right_pad(5)}] [${"abcdefg"?right_pad(5)}] [${"abcdefgh"?right_pad(5)}][${""?right_pad(8, ".oO")}] [${"a"?right_pad(8, ".oO")}] [${"ab"?right_pad(8, ".oO")}] [${"abc"?right_pad(8, ".oO")}] [${"abcd"?right_pad(8, ".oO")}]输出结果:[ ][a ][ab ][abc ][abcd ][abcde][abcdef][abcdefg][abcdefgh][.oO.oO.o][aoO.oO.o][abO.oO.o][abc.oO.o][abcdoO.o]contains()作用:判断一个集合是否存在某个对象例子:<#assign bb ><#list ["free","marker","freemarker"] as aa>${aa}</#list></#assign><#if bb?contains("marker")>包含了${bb}</#if>输出结果:包含了free marker freemarkermatchsnumberreplace()作用:替换字符串例子:${“this is the car”?replace(“car”,”freemarker”)} 输出结果:this is the freemarker rtfurlsplit()作用:分隔字符串例子:<#list "someMOOtestMOOtext"?split("MOO") as x>- ${x}</#list>输出结果:- some- test- textstarts_with()作用:判断是否存在字串,顺序是从左到右例子:${“FreeMarker”?starts_with(“ree”)} 输出结果:truestring()作用:例子:1.对数字类型的变量,默认的有四种格式:computer,currency,percent,number<#assign x=42>${x}${x?string} <#-- the same as ${x} -->${x?string.number}${x?string.currency}${x?string.percent}${x?puter}输出结果:424242$42.004,200%42也可以自己定义格式<#assign x = 1.234>${x?string("0")}${x?string("0.#")}${x?string("0.##")}${x?string("0.###")}${x?string("0.####")}${1?string("000.00")}${12.1?string("000.00")}${123.456?string("000.00")}${1.2?string("0")}${1.8?string("0")}${1.5?string("0")} <-- 1.5, rounded towards even neighbor ${2.5?string("0")} <-- 2.5, rounded towards even neighbor${12345?string("0.##E0")}输出结果:11.21.231.2341.234001.00012.10123.46122 <-- 1.5, rounded towards even neighbor2 <-- 2.5, rounded towards even neighbor1.23E42.对布尔值对象的使用例子:<#assign bl = true>${ bl?string(“yes”,”no”)} 输出结果:yestrim作用:去掉前后空格例子:${“FreeMarker “trim} 输出结果:FreeMarker upper_case作用:转换成大写例子:${“freemarker”?upper_case} 输出结果:FREEMARKER word_list作用:把字符串按照空格转化成sequence例子:<#assign seq = “the Free marker”?word_list><#list seq as item>${item}</#list>输出结果:theFreemarkerXmlC例子:${10?c} 输出结果: 10round ,floor,ceiling例子:<#assign testlist=[0, 1, -1, 0.5, 1.5, -0.5,-1.5, 0.25, -0.25, 1.75, -1.75]><#list testlist as result>${result} ?floor=${result?floor} ?ceiling=${result?ceiling} ?round=${ result?round}</#list>输出结果:0 ?floor=0 ?ceiling=0 ?round=01 ?floor=1 ?ceiling=1 ?round=1-1 ?floor=-1 ?ceiling=-1 ?round=-10.5 ?floor=0 ?ceiling=1 ?round=11.5 ?floor=1 ?ceiling=2 ?round=2-0.5 ?floor=-1 ?ceiling=0 ?round=0-1.5 ?floor=-2 ?ceiling=-1 ?round=-10.25 ?floor=0 ?ceiling=1 ?round=0-0.25 ?floor=-1 ?ceiling=0 ?round=01.75 ?floor=1 ?ceiling=2 ?round=2-1.75 ?floor=-2 ?ceiling=-1 ?round=-2first作用:返回sequence的第一个值例子:<% request.setAttribute(“lists”,list);%>${lists?first}<#assign x = [“free”,”marker”,”freemarker”]>${x?first} 输出结果:freelast作用:返回sequence的最后一个值例子:<% request.setAttribute(“lists”,list);%>${lists?last}<#assign x = [“free”,”marker”,”freemarker”]>${x?last} 输出结果:freemarkerseq_contains()作用:判断sequence中是否包含给出的值,返回true和false例子:<#assign x = ["red", 16, "blue", "cyan"]>"blue": ${x?seq_contains("blue")?string("yes", "no")} "yellow": ${x?seq_contains("yellow")?string("yes", "no")} 16: ${x?seq_contains(16)?string("yes", "no")}"16": ${x?seq_contains("16")?string("yes", "no")}输出结果:"blue": yes"yellow": no16: yes"16": noseq_index_of()作用:返回子串在sequence中第一出现的索引值,返回-1代表不存在子串例子:<#assign colors = ["red", "green", "blue"]>${colors?seq_index_of("blue")}${colors?seq_index_of("red")}${colors?seq_index_of("purple")}输出结果:2-1存在第二个参数的例子<#assign names = ["Joe", "Fred", "Joe", "Susan"]>No 2nd param: ${names?seq_index_of("Joe")}-2: ${names?seq_index_of("Joe", -2)}-1: ${names?seq_index_of("Joe", -1)}0: ${names?seq_index_of("Joe", 0)}1: ${names?seq_index_of("Joe", 1)}2: ${names?seq_index_of("Joe", 2)}3: ${names?seq_index_of("Joe", 3)}4: ${names?seq_index_of("Joe", 4)}输出结果:No 2nd param: 0-2: 0-1: 00: 01: 22: 23: -14: -1seq_last_index_of作用:返回子串在sequence最后出现的索引值,返回-1代表不存在该子串例子:<#assign names = ["Joe", "Fred", "Joe", "Susan"]>No 2nd param: ${names?seq_last_index_of("Joe")}-2: ${names?seq_last_index_of("Joe", -2)}-1: ${names?seq_last_index_of("Joe", -1)}0: ${names?seq_last_index_of("Joe", 0)}1: ${names?seq_last_index_of("Joe", 1)}2: ${names?seq_last_index_of("Joe", 2)}3: ${names?seq_last_index_of("Joe", 3)}4: ${names?seq_last_index_of("Joe", 4)}输出结果:No 2nd param: 2-2: -1-1: -10: 01: 02: 23: 24: 2reverse作用:反序输出sequence中的值例子:<#assign x = ["red", "16", "blue", "cyan"]?reverse >${x?first} 输出结果:cyansize作用:获得sequence的元素的数量例子:<#assign x = ["red", "16", "blue", "cyan"] >${x?size} 输出结果:4sort作用:对sequence中对象的tostring()结果进行排序例子:<#assign ls = ["whale", "Barbara", "zeppelin", "aardvark", "beetroot"]?sort> <#list ls as i> ${i}</#list>输出结果:aardvark Barbara beetroot whale zeppelinsort_by作用:对sequence 按里面的对象的属性value进行排序例子:<#assign ls = [{"name":"whale", "weight":2000},{"name":"Barbara", "weight":53},{"name":"zeppelin", "weight":-200},{"name":"aardvark", "weight":30},{"name":"beetroot", "weight":0.3}]>Order by name:<#list ls?sort_by("name") as i>- ${}: ${i.weight}</#list>Order by weight:<#list ls?sort_by("weight") as i>- ${}: ${i.weight}</#list>输出结果:Order by name:- aardvark: 30- Barbara: 53- beetroot: 0.3- whale: 2000- zeppelin: -200Order by weight:- zeppelin: -200- beetroot: 0.3- aardvark: 30- Barbara: 53- whale: 2000对于高级排序,在sequence中属性值也是sequence<#assign members = [{"name": {"first": "Joe", "last": "Smith"}, "age": 40},{"name": {"first": "Fred", "last": "Crooger"}, "age": 35},{"name": {"first": "Amanda", "last": "Fox"}, "age": 25}]> Sorted by st:<#list members?sort_by(['name', 'last']) as m>- ${st}, ${.first}: ${m.age} years old</#list>输出结果:Sorted by st:- Crooger, Fred: 35 years old- Fox, Amanda: 25 years old- Smith, Joe: 40 years oldchunk作用:分隔sequence成为几个子sequence,也可以给出默认的填充符例子:<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']><#list seq?chunk(4) as row><#list row as cell>${cell} </#list></#list><#list seq?chunk(4, '-') as row><#list row as cell>${cell} </#list></#list>输出结果:a b c de f g hi ja b c de f g hi j - -keys注意:不是所有的hash类型支持这个操作作用:返回hash里的所有keys,返回结果类型sequence例子:<#assign h = {"name":"mouse", "price":50}><#assign keys = h?keys><#list keys as key>${key} = ${h[key]}; </#list> 输出结果:name = mouse; price = 50;values注意:不是所有的hash类型支持这个操作作用:返回hash里的所有value, 返回结果类型sequence例子:<#assign h = {"name":"mouse", "price":50}> <#assign values = h?values><#list values as val>${val}-</#list>输出结果:mouse-50childrenParentRootAncestorsNode_name Node_typeNode_namespace。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
注释:由<#--和-->限定,不会输出
下面是以一个具体模板例子:
<html>[BR]
<head>[BR]
<title>Welcome!</title>[BR]
</head>[BR]
<body>[BR]
<#--Greettheuserwithhis/hername-->[BR]
(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"
<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>WelcomeBig Joe!</h1>
<p>Our latest product:
<a href="products/">green mouse</a>!
</body>
</html>
(2)数据模型
|
+- url = "products/"
|
+- name = "green mouse"
数据模型类似于计算机的文件系统,latestProduct可以看作是目录,而user、url和name看作是文件,url和name文件位于latestProduct目录中(这只是一个比喻,实际并不存在)
当FreeMarker将上面的数据模型合并到模板中,就创建了下面的输出:
<h1>Welcome${user}!</h1>[BR]
<p>Wehavetheseanimals:[BR]
<ul>[BR]
<#listanimalsasbeing>[BR]
<li>${}for${}Euros[BR]
</#list>[BR]
</ul>[BR]
</body>[BR]
</html>
[BR]是用于换行的特殊字符序列
经常会遇到的问题是:在Web页面(或其它类型的文档)中显示的信息在设计页面时是无效的,是基于动态数据的
在这里,你可以在HTML(或其它要输出的文本)中加入一些特定指令,FreeMarker会在输出页面给最终用户时,用适当的数据替代这些代码
下面是一个例子:
<html>
<head>
<title>Welcome!</title>
FreeMarker不是一个Web应用框架,而适合作为Web应用框架一个组件
FreeMarker与容器无关,因为它并不知道HTTP或Servlet;FreeMarker同样可以应用于非Web应用程序环境
FreeMarker更适合作为Model2框架(如Struts)的视图组件,你也可以在模板中使用JSP标记库
有两种类型的指令:预定义指令和用户定义指令
用户定义指令要使用@替换#,如<@mydirective>...</@mydirective>(会在后面讲述)
FTL标记不能够交叉,而应该正确的嵌套,如下面的代码是错误的:
<ul>
<#list animals as being>
<li>${} for ${} Eice = 5000
| |
| +- python
| |
| +- size = "medium"
| |
| +- price = 4999
|
+- test = "It is a test"
|
+- whatnot
|
+- because = "don't know"
类似于目录的变量称为hashes,包含保存下级变量的唯一的查询名字
典型的数据模型是树型结构,可以任意复杂和深层次,如下面的例子:
(root)
|
+- animals
| |
| +- mouse
| | |
| | +- size = "small"
| | |
| | +- price = 50
| |
| +- elephant
| | |
| | +- size = "large"
<tr>
<td>
<#if = "large"><b></#if>
${}
<#if = "large"></b></#if>
<td>${} Euros
</#list>
</table>
3、模板
(1)整体结构
模板使用FTL(FreeMarker模板语言)编写,是下面各部分的一个组合:
文本:直接输出
Interpolation:由${和},或#{和}来限定,计算值替代输出
|
+- (2nd) = "banana"
这种对scalars的访问使用索引,如animals[0].name
(3)模板
在FreeMarker模板中可以包括下面三种特定部分:
${…}:称为interpolations,FreeMarker会在输出时用实际值进行替代
FTL标记(FreeMarker模板语言标记):类似于HTML标记,为了与HTML标记区分,用#开始(有些以@开始,在后面叙述)
<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>
至于user、和来自于数据模型(data model)
数据模型由程序员编程来创建,向模板提供变化的信息,这些信息来自于数据库、文件,甚至于在程序中直接生成
模板设计者不关心数据从那儿来,只知道使用已经建立的数据模型
下面是一个可能的数据模型:
(root)
|
+- user = "Big Joe"
|
+- latestProduct
3、通用数据模型
FreeMarker不是直接反射到Java对象,Java对象通过插件式对象封装,以变量方式在模板中显示
你可以使用抽象(接口)方式表示对象(JavaBean、XML文档、SQL查询结果集等等),告诉模板开发者使用方法,使其不受技术细节的打扰
4、为Web准备
在模板语言中内建处理典型Web相关任务(如HTML转义)的结构
animalsas[BR]
being[BR]
>[BR]
注释:包含在<#--和-->(而不是<!--和-->)之间
下面是一些使用指令的例子:
if指令
<#if <Pythons are cheaper than elephants today.
<#else>
Pythons are not cheaper than elephants today.
</#if>
<h1>Welcome${user<#-- The name of user -->}!</h1>[BR]
<p>Wehavetheseanimals:[BR]
<ul>[BR]
<#list<#-- some comment... -->animals as<#-- again... -->being>[BR]