FreeMarker的模板文件并不比HTML页面复杂多少,FreeMarker模板文件主要由如下4个部分组成:1,文本:直接输出的部分2,注释:#--...--格式部分,不会输出3,插值:即${...}或#{...}格式的部分,将使用数据模型中的部分替代输出4,FTL指令:FreeMarker指定,和HTML标记类似,名字前加#予以区分,不会输出下面是一个FreeMarker模板的例子,包含了以上所说的4个部分htmlbrheadbrtitleWelcome!/titlebr/headbrbodybr#--注释部分--br#--下面使用插值--h1Welcome${user}!/h1brpWehavetheseanimals:bru1br#--使用FTL指令--#listanimalsasbeingbrli${being.name}for${being.price}Eurosbr#listbru1br/bodybr/html1,FTL指令规则在FreeMarker中,使用FTL标签来使用指令,FreeMarker有3种FTL标签,这和HTML标签是完全类似的.1,开始标签:#directivenameparameter2,结束标签:/#directivename3,空标签:#directivenameparameter/实际上,使用标签时前面的符号#也可能变成@,如果该指令是一个用户指令而不是系统内建指令时,应将#符号改成@符号.使用FTL标签时,应该有正确的嵌套,而不是交叉使用,这和XML标签的用法完全一样.如果全用不存在的指令,FreeMarker不会使用模板输出,而是产生一个错误消息.FreeMarker会忽略FTL标签中的空白字符.值得注意的是,/和指令之间不允许有空白字符.2,插值规则FreeMarker的插值有如下两种类型:1,通用插值${expr};2,数字格式化插值:#{expr}或#{expr;format}2.1通用插值对于通用插值,又可以分为以下4种情况:1,插值结果为字符串值:直接输出表达式结果2,插值结果为数字值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:#settionnumber_format=currency/#assignanswer=42/${answer}${answer?string}#--thesameas${answer}--${answer?string.number}${answer?string.currency}${answer?string.percent}${answer}输出结果是:$42.00$42.0042$42.004,200%3,插值结果为日期值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:${lastUpdated?string(yyyy-MM-ddHH:mm:sszzzz)}${lastUpdated?string(EEE,MMMd,''yy)}${lastUpdated?string(EEEE,MMMMdd,yyyy,hh:mm:ssa'('zzz')')}输出结果是:2008-04-0808:08:08PacificDaylightTimeTue,Apr8,'03Tuesday,April08,2003,08:08:08PM(PDT)4,插值结果为布尔值:根据默认格式(由#setting指令设置)将表达式结果转换成文本输出.可以使用内建的字符串函数格式化单个插值,如下面的例子:#assignfoo=true/${foo?string(yes,no)}输出结果是:yes2.2数字格式化插值数字格式化插值可采用#{expr;format}形式来格式化数字,其中format可以是:mX:小数部分最小X位MX:小数部分最大X位如下面的例子:#assignx=2.582/#assigny=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:\盘我名字是annleeFreeMarker支持如下转义字符:\;双引号(u0022)\';单引号(u0027)\\;反斜杠(u005C)\n;换行(u000A)\r;回车(u000D)\t;Tab(u0009)\b;退格键(u0008)\f;Formfeed(u000C)\l;\g;\a;&\{;{\xCode;直接通过4位的16进制数来指定Unicode码,输出该unicode码对应的字符.如果某段文本中包含大量的特殊符号,FreeMarker提供了另一种特殊格式:可以在指定字符串内容的引号前增加r标记,在r标记后的文件将会直接输出.看如下代码:${r${foo}}${rC:\foo\bar}输出结果是:${foo}C:\foo\bar2,数值表达式中的数值直接输出,不需要引号.小数点使用.分隔,不能使用分组,符号.FreeMarker目前还不支持科学计数法,所以1E3是错误的.在FreeMarker表达式中使用数值需要注意以下几点:1,数值不能省略小数点前面的0,所以.5是错误的写法2,数值8,+8,8.00都是相同的3,布尔值直接使用true和false,不使用引号.4,集合集合以方括号包括,各集合元素之间以英文逗号,分隔,看如下的例子:#list[星期一,星期二,星期三,星期四,星期五,星期六,星期天]asx${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,顶层变量所谓顶层变量就是直接放在数据模型中的值,例如有如下数据模型:Maproot=newHashMap();//创建数据模型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元素的值,可以使用点语法或方括号语法.假如有下面的数据模型:Maproot=newHashMap();Bookbook=newBook();Authorauthor=newAuthor();author.setName(annlee);author.setAddress(gz);book.setName(struts2);book.setAuthor(author);root.put(info,struts);root.put(book,book);为了访问数据模型中名为struts2的书的作者的名字,可以使用如下语法:book.author.name//全部使用点语法book[author].namebook.author[name]//混合使用点语法和方括号语法book[author][name]//全部使用方括号语法使用点语法时,变量名字有顶层变量一样的限制,但方括号语法没有该限制,因为名字可以是任意表达式的结果.3.3,字符串操作FreeMarker的表达式对字符串操作非常灵活,可以将字符串常量和变量连接起来,也可以返回字符串的子串等.字符串连接有两种语法:1,使用${..}或#{..}在字符串常量部分插入表达式的值,从而完成字符串连接.2,直接使用连接运算符+来连接字符串例如有如下数据模型:Maproot=newHashMap();root.put(user,annlee);下面将user变量和常量连接起来:${hello,${user}!}//使用第一种语法来连接${hello,+user+!}//使用+号来连接上面的输出字符串都是hello,annlee!,可以看出这两种语法的效果完全一样.值得注意的是,${..}只能用于文本部分,不能用于表达式,下面的代码是错误的:#if${isBig}Wow!/#if#if${isBig}Wow!/#if应该写成:#ifisBigWow!/#if截取子串可以根据字符串的索引来进行,截取子串时如果只指定了一个索引值,则用于取得字符串中指定索引所对应的字符;如果指定两个索引值,则返回两个索引中间的字符串子串.假如有如下数据模型:Maproot=newHashMap();root.put(book,struts2,freemarker);可以通过如下语法来截取子串:${book[0]}${book[4]}//结果是su${book[1..4]}//结果是tru3.4集合连接运算符这里所说的集合运算符是将两个集合连接成一个新的集合,连接集合的运算符是+,看如下的例子:#list[星期一,星期二,星期三]+[星期四,星期五,星期六,星期天]asx${x}/#list输出结果是:星期一星期二星期三星期四星期五星期六星期天3.5Map连接运算符Map对象的连接运算符也是将两个Map对象连接成一个新的Map对象,Map对象的连接运算符是+,如果两个Map对象具有相同的key,则右边的值替代左边的值.看如下的例子:#assignscores={语文:86,数学:7