FreeMarker是一个用Java编写的模板引擎,主要用来生成HTML Web页面,特别是基于MVC模式的应用程序。虽然 FreeMarker具有一些编程的能力,但不像PHP,通常由Java程序准备要显示的数据,由 FreeMarker模板生成页面。 FreeMarker可以作为Web应用框架一个组件,但它与容器无关,在非Web应用程序环境也能工作的很好。 FreeMarker适合作为MVC的视图组件,还能在模板中使用JSP标记库。
Java代码 复制代码
  1. <html>    
  2. <head>    
  3. <title>Welcome!</title>    
  4. </head>    
  5. <body>    
  6. <h1>Welcome ${user}!</h1>    
  7. <p>Our latest product:    
  8. <a href="${latestProduct.url}">${latestProduct.name}</a>!    
  9. </body>    
  10. </html>   

上面的例子中,在简单的HTML中加入了一些由${…}包围的特定 FreeMarker的指令,这个文件就称为模板了。而user、latestProduct.url和latestProduct.name来自于数据模型,由Java程序提供,模板设计者就不用关心数据从哪来的。
FreeMarker模板中可以包括下面四种特定部分:
一)文本:直接输出

二)FTL标记(FreeMarker模板语言标记):类似于HTML标记,名字前加#(有些以@开始,用户自定义标记)予以区分,不会输出。
1.字符串:使用单引号或双引号限定;如果包含特殊字符需要转义符:${"It's /"quoted/" andthis is a backslash: //"}
有一类特殊的字符串:${r"C:/foo/bar"},输出结构为:C:/foo/bar,在引号前面加r被认为是纯文本。

2.数字:直接输入,不需要引号。${08}, ${+8}, ${8.00} and ${8} 都是相同的

3.布尔值:true和false,不使用引号

4.Sequences(序列)
a.由逗号分隔的变量列表,由方括号限定,类似java中的一维数组:
例一:["winter", "spring", "summer", "autumn"]
例二:[2 + 2, [1, 2, 3, 4], "whatnot"] (可以嵌套)
例三:2..5,等同于[2, 3, 4, 5];5..2,等同于[5,4,3,2]。
注意方括号是不需要的。 (另外写法)
b.获取Sequence(序列)中元素-使用[startindex..endindex]
例如:seq中存储了"a", "b", "c", "d","e",
那么seq[1..2]包含了b和c两个值。
c.Sequences(序列)元素的遍历
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
${user}
</#list>
5.Hashes(散列)
由逗号分隔的键-值列表,由大括号限定,键和值之间用冒号分隔:{"name":"green mouse", "price":150},键和值都是表达式,但是键必须是字符串。
获取变量-${variable},变量名只能是字母、数字、下划线、$、@和#的组合,且不能以数字开头。可以使用.variablename语法访问 FreeMarker内置变量。 下列表达式是等价的:
book.author.name
book["author"].name
book.author.["name"]
book["author"]["name"]

6.字符串操作
{"Hello ${user}!"} <==> ${"Hello " + user + "!"}
${"${user}${user}${user}${user}"} <==> ${user + user + user + user}
${…}只能在文本中使用,下面是错误的代码:
<#if ${isBig}>Wow!</#if>
<#if "${isBig}">Wow!</#if> //此处的代码也是错误的,因为if指令需要的是boolean,实际的却是个字符串
子字符串的操作,
<#assign user="Big Joe">
${user[0]}${user[4]} <==> BJ
${user[1..4]} <==> ig J
注意: 操作符两边必须是数字;使用"+"时,如果一边是数字,一边是字符串,就会自动将数字转换为字符串。

7.使用内建的指令int获得整数部分:
${(x/2)?int}
${1.1?int}
${1.999?int}
${-1.1?int}
${-1.999?int}

8.比较操作符-<#if expression>...</#if>
1.)使用=(或==,完全相等)测试两个值是否相等,使用!= 测试两个值是否不相等
2.)=和!=两边必须是相同类型的值,否则会产生错误,例如<#if 1 = "1">会引起错误
3.) Freemarker是精确比较,所以"x"、"x "和"X"是不相等的
4.)对数字和日期可以使用<、<=、>和>=,但不能用于字符串
5.)由于 Freemarker会将>解释成FTL标记的结束字符,所以对于>和>=可以使用括号来避免这种情况,例如<#if (x > y)>,另一种替代的方法是,使用lt、lte、gt和gte来替代<、<=、>和>=
6.)逻辑操作符-&&(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>

9.内置函数-用法类似访问hash(散列)的子变量,只是使用"?"替代".",
例如:user?upper_case
下面列出常用的一些函数:
对于字符串
html-对字符串进行HTML编码
cap_first-使字符串第一个字母大写
lower_case-将字符串转换成小写
trim-去掉字符串前后的空白字符
对于Sequences(序列)
size-获得序列中元素的数目
对于数字
int-取得数字的整数部分(如-1.9?int的结果是-1)

10.方法的调用
${repeat("What", 3)}
${repeat(repeat("x", 2), 3) + repeat("What", 4)?upper_case}
结果:
WhatWhatWhat
xxxxxxWHATWHATWHATWHAT

11.操作符优先顺序
后缀 [subvarName] [subStringRange] . (methodParams)
一元 +expr、-expr、!
内建 ?
乘法 *、 / 、%
加法 +、-
关系 <、>、<=、>=(lt、lte、gt、gte)
相等 =、!=
逻辑 &&
逻辑 ||
数字范围 ..

12.一些常用控制语句
1)if, else, elseif
Java代码 复制代码
  1. <#if x == 1>   
  2.   x is 1  
  3.   <#if y == 1>   
  4.     and y is 1 too   
  5.   <#else>   
  6.     but y is not   
  7.   </#if>   
  8. <#else>   
  9.   x is not 1  
  10.   <#if y < 0>   
  11.     and y is less than 0  
  12.   </#if>   
  13. </#if>   

2)switch, case, default, break
<#switch value>
Java代码 复制代码
  1.  <#switch being.size>   
  2.   <#case "small">   
  3.      This will be processed if it is small   
  4.      <#break>   
  5.   <#case "medium">   
  6.      This will be processed if it is medium   
  7.      <#break>   
  8.   <#case "large">   
  9.      This will be processed if it is large   
  10.      <#break>   
  11.   <#default>   
  12.      This will be processed if it is neither   
  13. </#switch>   

3) list, break
Java代码 复制代码
  1. <#list sequence as item>   
  2.   ${item}   
  3.   <#if item = "xx"><#break></#if>   
  4. </#list>    

4)include
Java代码 复制代码
  1. <#include "/common/navbar.html" parse=false encoding="Shift_JIS">  

5)import
Java代码 复制代码
  1. <#import "/libs/mylib.ftl" as my>   
  2. <@my.copyright date="1999-2002"/>  

Note: that it is possible to automatically do the commonly used imports for all templates, with the "auto imports" setting of Configuration.
6)noparse
Java代码 复制代码
  1. <#noparse>   
  2.   <#list animals as being>   
  3.   <tr><td>${being.name}<td>${being.price} Euros   
  4.   </#list>   
  5. </#noparse>  

7)compress
Java代码 复制代码
  1. <#assign x = "    moo  /n/n   ">   
  2. (<#compress>   
  3.   1 2  3   4    5  
  4.   ${moo}   
  5.   test only   
  6.   
  7.   I said, test only   
  8.   
  9. </#compress>)   

8)escape, noescape
Java代码 复制代码
  1. <#assign x = "<test>">   
  2. <#macro m1>   
  3.   m1: ${x}   
  4. </#macro>   
  5. <#escape x as x?html>   
  6.   <#macro m2>m2: ${x}</#macro>   
  7.   ${x}   
  8.   <@m1/>   
  9. </#escape>   
  10. ${x}   
  11. <@m2/>     
  12.     
  13.  <#escape x as x?html>   
  14.   From: ${mailMessage.From}   
  15.   Subject: ${mailMessage.Subject}   
  16.   <#noescape>Message: ${mailMessage.htmlFormattedBody}</#noescape>   
  17.   ...   
  18. </#escape>    
  19.   
  20. <#escape x as x?html>   
  21.   Customer Name: ${customerName}   
  22.   Items to ship:   
  23.   <#escape x as itemCodeToNameMap[x]>   
  24.     ${itemCode1}   
  25.     ${itemCode2}   
  26.     ${itemCode3}   
  27.     ${itemCode4}   
  28.   </#escape>   
  29. </#escape>    

9)assign
Java代码 复制代码
  1. <#import "/mylib.ftl" as my>   
  2. <#assign   
  3.   seasons = ["winter""spring""summer""autumn"]   
  4.   test = test + 1  
  5.    bgColor="red" in my   
  6. >     
  7. <#macro myMacro>foo</#macro>   
  8. <#assign x>   
  9.   <#list 1..3 as n>   
  10.     ${n} <@myMacro />   
  11.   </#list>   
  12. </#assign>   
  13. Number of words: ${x?word_list?size}   
  14. ${x}     
  15. <#assign x="Hello ${user}!">   

10)global
Java代码 复制代码
  1. <#global name=value>   
  2. or   
  3. <#global name1=value1 name2=value2 ... nameN=valueN>   
  4. or   
  5. <#global name>   
  6.   capture this  
  7. </#global>  

11)local
note:it is similar to assign directive, but it creates or replaces local variables. This works in macro definition bodies only.
Java代码 复制代码
  1. <#local name=value>   
  2. or   
  3. <#local name1=value1 name2=value2 ... nameN=valueN>   
  4. or   
  5. <#local name>   
  6.   capture this  
  7. </#local>  

12)setting
note:The supported settings are:locale,number_format,boolean_format,
date_format, time_format, datetime_format,time_zone,url_escaping_charset,classic_compatible
Java代码 复制代码
  1. ${1.2}   
  2. <#setting locale="en_US">   
  3. ${1.2}   

13) (<@...>)
Java代码 复制代码
  1. <@myRepeatMacro count=4 ; x, last>   
  2.   ${x}. Something... <#if last> This was the last!</#if>   
  3. </@myRepeatMacro>    

14)macro, nested, return
Java代码 复制代码
  1. <#macro img src extra...>   
  2.   <img src="/context${src?html}"    
  3.   <#list extra?keys as attr>   
  4.     ${attr}="${extra[attr]?html}"  
  5.   </#list>   
  6.   >   
  7. </#macro>   
  8. <@img src="/images/test.png" width=100 height=50 alt="Test"/>   
  9.   
  10. <#macro repeat count>   
  11.   <#list 1..count as x>   
  12.     <#nested x, x/2, x==count>   
  13.   </#list>   
  14. </#macro>   
  15. <@repeat count=4 ; c, halfc, last>   
  16.   ${c}. ${halfc}<#if last> Last!</#if>   
  17. </@repeat>     
  18. <#macro test>   
  19.   Test text   
  20.   <#return>   
  21.   Will not be printed.   
  22. </#macro>   
  23. <@test/>    

15)function, return

Java代码 复制代码
  1. <#function avg nums...>   
  2.   <#local sum = 0>   
  3.   <#list nums as num>   
  4.     <#local sum = sum + num>   
  5.   </#list>   
  6.   <#if nums?size != 0>   
  7.     <#return sum / nums?size>   
  8.   </#if>   
  9. </#function>   
  10. ${avg(1020)}   
  11. ${avg(10203040)}   
  12. ${avg()!"N/A"}   

16).flush
17)stop
18)ftl
19)t, lt, rt

20)nt
21)attempt, recover

Java代码 复制代码
  1. Primary content   
  2. <#attempt>   
  3.   Optional content: ${thisMayFails}   
  4. <#recover>   
  5.   Ops! The optional content is not available.   
  6. </#attempt>   
  7. Primary content continued    

22)visit, recurse, fallback


三. Interpolation:由${...}或#{...}两种类型,输出计算值,可以自定义输出的格式
1)string的操作:
substring
cap_first
uncap_first
capitalize
chop_linebreak
date, time, datetime
ends_with
html
groups
index_of
j_string
js_string
last_index_of
length
lower_case
left_pad
right_pad
contains
matches
number
replace
rtf
url
split
starts_with
string (when used with a string value)
trim
upper_case
word_list
xml

2)numbers的操作:
c
string (when used with a numerical value)
round, floor, ceiling


3)dates的操作:
string (when used with a date value)
date, time, datetime

4)booleans的操作:
string (when used with a boolean value)
5)sequences的操作:
first
last
seq_contains
seq_index_of
seq_last_index_of
reverse
size
sort
sort_by
chunk

6)hashes的操作:
keys
values

7)nodes 的操作:
children
parent
root
ancestors
node_name
node_type
node_namespace


四.) 注释:<#--和-->




下面是一个常用的模板例子:
例一:
Java代码 复制代码
  1. <p>We have these animals:    
  2. <table border=1>    
  3. <tr><th>Name<th>Price    
  4. <#list animals as being>    
  5. <tr>    
  6. <td>    
  7. <#if being.size = "large"><b></#if>    
  8. ${being.name}    
  9. <#if being.size="large"></b></#if>    
  10. <td>${being.price} Euros    
  11. </#list>    
  12. </table>    
  13. <#include "/copyright_footer.html">   

注意点:
1.) FreeMarker是区分大小写的;
2.) FTL标记不能位于另一个FTL标记内部,例如:<#if <#include 'foo'>='bar'>...</if>;
3.) ${…}只能在文本中使用;
4.) 多余的空白字符会在模板输出时去除;
5.) 如果使用的指令不存在,会产生一个错误消息。

例子2。
Java代码 复制代码
  1. <%@ taglib uri="/WEB-INF/fmtag.tld" prefix="fm" %>   
  2. <jsp:useBean id="mybean"  class="<SPAN class=hilite1>freemarker</SPAN>.examples.jsp.SimpleBean"/>   
  3. <jsp:useBean id="mybeanreq" class="<SPAN class=hilite1>freemarker</SPAN>.examples.jsp.SimpleBean" scope="request"/>   
  4. <fm:template>   
  5. <html>   
  6.   <head>   
  7.     <title><SPAN class=hilite1>FreeMarker</SPAN> JSP Example</title>   
  8.   </head>   
  9.   <body>   
  10.     <h1><SPAN class=hilite1>FreeMarker</SPAN> JSP example</h1>   
  11.     <hr>   
  12.     <p>   
  13.       This page is a JSP page, yet most of its contents is generated using   
  14.       a <SPAN class=hilite1>FreeMarker</SPAN> template. The below lines are the output of calling   
  15.       properties on a JSP-declared bean from the <SPAN class=hilite1>FreeMarker</SPAN> template:   
  16.     </p>   
  17.        
  18.     <#assign mybean = page.mybean>   
  19.     <#assign mybeanreq = request.mybeanreq>   
  20.        
  21.     <p>page: ${mybean.string}   
  22.     <#list mybean.array as item>   
  23.       <br>${item}   
  24.     </#list>   
  25.     <br>request : ${mybeanreq.string}   
  26.        
  27.     <p><b>Note:</b> Starting from <SPAN class=hilite1>FreeMarker</SPAN> 2.2 you can use custom JSP tags in   
  28.        <SPAN class=hilite1>FreeMarker</SPAN> templates. If you want to migrate from JSP to FTL (i.e. <SPAN class=hilite1>FreeMarker</SPAN> templates),   
  29.        then that's probably a better option than embedding FTL into JSP pages.   
  30. </body>   
  31. </html>   
  32. </fm:template>  

fmtag.tld文件:

Java代码 复制代码
  1. <?xml version="1.0" encoding="ISO-8859-1" ?>   
  2. <!DOCTYPE taglib   
  3.         PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"  
  4.         "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">   
  5.   
  6. <taglib>   
  7.   
  8.   <tlibversion>2.0</tlibversion>   
  9.   <jspversion>1.1</jspversion>   
  10.   <shortname><SPAN class=hilite1>FreeMarker</SPAN> JSP Support</shortname>   
  11.   
  12.   <tag>   
  13.     <name>template</name>   
  14.     <tagclass><SPAN class=hilite1>freemarker</SPAN>.ext.jsp.<SPAN class=hilite1>Freemarker</SPAN>Tag</tagclass>   
  15.     <bodycontent>tagdependent</bodycontent>   
  16.     <info>Allows evaluation of <SPAN class=hilite1>FreeMarker</SPAN> templates inside JSP</info>   
  17.     <attribute>   
  18.       <name>caching</name>   
  19.       <required>false</required>   
  20.     </attribute>   
  21.   </tag>   
  22. </taglib>  


例子3:
inedex.ftl 代码:

Java代码 复制代码
  1. <#import "/lib/common.ftl" as com>   
  2. <#escape x as x?html>   
  3.   
  4. <@com.page title="Index">   
  5.   <a href="form.do">Add new message</a> | <a href="help.html">Help</a>   
  6.   <#if guestbook?size = 0>   
  7.     <p>No messages.   
  8.   <#else>   
  9.     <p>The messages are:   
  10.     <table border=0 cellspacing=2 cellpadding=2 width="100%">   
  11.       <tr align=center valign=top>   
  12.         <th bgcolor="#C0C0C0">Name   
  13.         <th bgcolor="#C0C0C0">Message   
  14.       <#list guestbook as e>   
  15.         <tr align=left valign=top>   
  16.           <td bgcolor="#E0E0E0">${e.name} <#if e.email?length != 0> (<a href="mailto:${e.email}">${e.email}</a>)</#if>   
  17.           <td bgcolor="#E0E0E0">${e.message}   
  18.       </#list>   
  19.     </table>   
  20.   </#if>   
  21. </@com.page>   
  22. </#escape>  


form.ftl代码
Java代码 复制代码
  1. <#import "/lib/common.ftl" as com>   
  2. <#global html=JspTaglibs["/WEB-INF/struts-html.tld"]>   
  3. <#escape x as x?html>   
  4.   
  5. <@com.page title="Add Entry">   
  6.   <@html.errors/>   
  7.      
  8.   <@html.form action="/add">   
  9.     <p>Your name:<br>   
  10.     <@html.text property="name" size="60"/>   
  11.     <p>Your e-mail (optional):<br>   
  12.     <@html.text property="email" size="60"/>   
  13.     <p>Message:<br>   
  14.     <@html.textarea property="message" rows="3" cols="60"/>   
  15.     <p><@html.submit value="Submit"/>   
  16.   </@html.form>   
  17.      
  18.   <p><a href="index.do">Back to the index page</a>   
  19. </@com.page>   
  20. </#escape>  

add.ftl代码内容
Java代码 复制代码
  1. <#import "/lib/common.ftl" as com>   
  2. <#escape x as x?html>   
  3.   
  4. <@com.page title="Entry added">   
  5.   <p>You have added the following entry to the guestbook:   
  6.   <p><b>Name:</b> ${guestbookEntry.name}   
  7.   <#if guestbookEntry.email?length != 0>   
  8.     <p><b>Email:</b> ${guestbookEntry.email}   
  9.   </#if>   
  10.   <p><b>Message:</b> ${guestbookEntry.message}   
  11.   <p><a href="index.do">Back to the index page...</a>   
  12. </@com.page>   
  13. </#escape>  

common.ftl的 代码
Java代码 复制代码
  1. <#macro page title>   
  2.   <html>   
  3.   <head>   
  4.     <title><SPAN class=hilite1>FreeMarker</SPAN> Struts Example - ${title?html}</title>   
  5.     <meta http-equiv="Content-type" content="text/html; charset=ISO-8859-1">   
  6.   </head>   
  7.   <body>   
  8.     <h1>${title?html}</h1>   
  9.     <hr>   
  10.     <#nested>   
  11.     <hr>   
  12.     <table border="0" cellspacing=0 cellpadding=0 width="100%">   
  13.       <tr valign="middle">   
  14.         <td align="left">   
  15.           <i><SPAN class=hilite1>FreeMarker</SPAN> Struts Example</i>   
  16.         <td align="right">   
  17.           <a href="http://<SPAN class=hilite1>freemarker</SPAN>.org"><img src="poweredby_ffffff.png" border=0></a>   
  18.     </table>   
  19.   </body>   
  20.   </html>   
  21. </#macro>  

FreeMarker内部运行的某些原理:
个人感觉有兴趣和时间的人可以去研究下《Programmer Guide》部分(原文档共有四个部分)该部分主要是介绍 FreeMarker内部运行的某些原理
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐