Freemark 开发指南初稿<o:p></o:p>
整理:蒋江伟
A概念
最常用的3个概念
sequence 序列,对应java里的list、数组等非键值对的集合<o:p></o:p>
hash 键值对的集合<o:p></o:p>
namespace 对一个ftl文件的引用,利用这个名字可以访问到该ftl文件的资源<o:p></o:p>
<o:p> </o:p>
B指令<o:p></o:p>
if, else, elseif<o:p></o:p>
语法
<#if condition><o:p></o:p>
...<o:p></o:p>
<#elseif condition2><o:p></o:p>
...<o:p></o:p>
<#elseif condition3><o:p></o:p>
...<o:p></o:p>
...<o:p></o:p>
<#else><o:p></o:p>
...<o:p></o:p>
</#if><o:p></o:p>
用例<o:p></o:p>
<#if x = 1><o:p></o:p>
x is 1<o:p></o:p>
</#if><o:p></o:p>
<o:p> </o:p>
<#if x = 1><o:p></o:p>
x is 1<o:p></o:p>
<#else><o:p></o:p>
x is not 1<o:p></o:p>
</#if><o:p></o:p>
<o:p> </o:p>
switch, case, default, break<o:p></o:p>
语法
<#switch value><o:p></o:p>
<#case refValue1><o:p></o:p>
...<o:p></o:p>
<#break><o:p></o:p>
<#case refValue2><o:p></o:p>
...<o:p></o:p>
<#break><o:p></o:p>
...<o:p></o:p>
<#case refValueN><o:p></o:p>
...<o:p></o:p>
<#break><o:p></o:p>
<#default><o:p></o:p>
...<o:p></o:p>
</#switch><o:p></o:p>
<o:p> </o:p>
用例
字符串
<#switch being.size><o:p></o:p>
<#case "small"><o:p></o:p>
This will be processed if it is small<o:p></o:p>
<#break><o:p></o:p>
<#case "medium"><o:p></o:p>
This will be processed if it is medium<o:p></o:p>
<#break><o:p></o:p>
<#case "large"><o:p></o:p>
This will be processed if it is large<o:p></o:p>
<#break><o:p></o:p>
<#default><o:p></o:p>
This will be processed if it is neither<o:p></o:p>
</#switch><o:p></o:p>
数字<o:p></o:p>
<#switch x><o:p></o:p>
<#case x = 1><o:p></o:p>
1<o:p></o:p>
<#case x = 2><o:p></o:p>
2<o:p></o:p>
<#default><o:p></o:p>
d<o:p></o:p>
</#switch><o:p></o:p>
<o:p> </o:p>
如果x=1 输出 1 2, x=2输出 2, x=3 输出d<o:p></o:p>
<o:p> </o:p>
list, break<o:p></o:p>
语法
<#list sequence as item><o:p></o:p>
...<o:p></o:p>
<#if item = "spring"><#break></#if><o:p></o:p>
...<o:p></o:p>
</#list><o:p></o:p>
关键字<o:p></o:p>
item_index:是list当前值的下标<o:p></o:p>
item_has_next:判断list是否还有值<o:p></o:p>
<o:p> </o:p>
用例<o:p></o:p>
<#assign seq = ["winter", "spring", "summer", "autumn"]><o:p></o:p>
<#list seq as x><o:p></o:p>
${x_index + 1}. ${x}<#if x_has_next>,</#if><o:p></o:p>
</#list><o:p></o:p>
<o:p> </o:p>
输出<o:p></o:p>
1. winter,<o:p></o:p>
2. spring,<o:p></o:p>
3. summer,<o:p></o:p>
4. autumn <o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
include<o:p></o:p>
语法
<#include filename><o:p></o:p>
or<o:p></o:p>
<#include filename options><o:p></o:p>
options包含两个属性<o:p></o:p>
encoding=”GBK” 编码格式<o:p></o:p>
parse=true 是否作为ftl语法解析,默认是true,false就是以文本方式引入.注意在ftl文件里布尔值都是直接赋值的如parse=true,而不是parse=”true”<o:p></o:p>
用例<o:p></o:p>
/common/copyright.ftl包含内容<o:p></o:p>
Copyright 2001-2002 ${me}<br><o:p></o:p>
All rights reserved. <o:p></o:p>
模板文件<o:p></o:p>
<#assign me = "Juila Smith"><o:p></o:p>
<h1>Some test</h1><o:p></o:p>
<p>Yeah.<o:p></o:p>
<hr><o:p></o:p>
<#include "/common/copyright.ftl" encoding=”GBK”> <o:p></o:p>
输出结果<o:p></o:p>
<h1>Some test</h1><o:p></o:p>
<p>Yeah.<o:p></o:p>
<hr><o:p></o:p>
Copyright 2001-2002 Juila Smith<o:p></o:p>
All rights reserved. <o:p></o:p>
<o:p> </o:p>
Import<o:p></o:p>
语法
<#import path as hash><o:p></o:p>
类似于java里的import,它导入文件,然后就可以在当前文件里使用被导入文件里的宏组件<o:p></o:p>
<o:p> </o:p>
用例<o:p></o:p>
<o:p> </o:p>
假设mylib.ftl里定义了宏copyright那么我们在其他模板页面里可以这样使用<o:p></o:p>
<#import "/libs/mylib.ftl" as my><o:p></o:p>
<o:p> </o:p>
<@my.copyright date="1999-2002"/><o:p></o:p>
<o:p> </o:p>
"my"在freemarker里被称作namespace<o:p></o:p>
<o:p> </o:p>
compress<o:p></o:p>
语法
<#compress><o:p></o:p>
...<o:p></o:p>
</#compress><o:p></o:p>
用来压缩空白空间和空白的行<o:p></o:p>
用例<o:p></o:p>
<#assign x = " moo \n\n "><o:p></o:p>
(<#compress><o:p></o:p>
1 2 3 4 5<o:p></o:p>
${moo}<o:p></o:p>
test only<o:p></o:p>
<o:p> </o:p>
I said, test only<o:p></o:p>
<o:p> </o:p>
</#compress>) <o:p></o:p>
输出<o:p></o:p>
(1 2 3 4 5<o:p></o:p>
moo<o:p></o:p>
test only<o:p></o:p>
I said, test only) <o:p></o:p>
escape, noescape<o:p></o:p>
语法
<#escape identifier as expression><o:p></o:p>
...<o:p></o:p>
<#noescape>...</#noescape><o:p></o:p>
...<o:p></o:p>
</#escape><o:p></o:p>
用例<o:p></o:p>
主要使用在相似的字符串变量输出,比如某一个模块的所有字符串输出都必须是html安全的,这个时候就可以使用该表达式<o:p></o:p>
<#escape x as x?html><o:p></o:p>
First name: ${firstName}<o:p></o:p>
<#noescape>Last name: ${lastName}</#noescape><o:p></o:p>
Maiden name: ${maidenName}<o:p></o:p>
</#escape><o:p></o:p>
相同表达式 <o:p></o:p>
First name: ${firstName?html}<o:p></o:p>
Last name: ${lastName }<o:p></o:p>
Maiden name: ${maidenName?html}<o:p></o:p>
assign<o:p></o:p>
语法
<#assign name=value><o:p></o:p>
or<o:p></o:p>
<#assign name1=value1 name2=value2 ... nameN=valueN><o:p></o:p>
or<o:p></o:p>
<#assign same as above... in namespacehash><o:p></o:p>
or<o:p></o:p>
<#assign name><o:p></o:p>
capture this<o:p></o:p>
</#assign><o:p></o:p>
or<o:p></o:p>
<#assign name in namespacehash><o:p></o:p>
capture this<o:p></o:p>
</#assign><o:p></o:p>
用例<o:p></o:p>
生成变量,并且给变量赋值<o:p></o:p>
给seasons赋予序列值<o:p></o:p>
<#assign seasons = ["winter", "spring", "summer", "autumn"]><o:p></o:p>
<o:p> </o:p>
给变量test加1<o:p></o:p>
<#assign test = test + 1><o:p></o:p>
<o:p> </o:p>
给my namespage 赋予一个变量bgColor,下面可以通过my.bgColor来访问这个变量<o:p></o:p>
<#import "/mylib.ftl" as my><o:p></o:p>
<#assign bgColor="red" in my><o:p></o:p>
<o:p> </o:p>
将一段输出的文本作为变量保存在x里<o:p></o:p>
下面的阴影部分输出的文本将被赋值给x<o:p></o:p>
<#assign x><o:p></o:p>
<#list 1..3 as n><o:p></o:p>
${n} <@myMacro /><o:p></o:p>
</#list><o:p></o:p>
</#assign><o:p></o:p>
Number of words: ${x?word_list?size}<o:p></o:p>
${x}<o:p></o:p>
<o:p> </o:p>
<#assign x>Hello ${user}!</#assign> error<o:p></o:p>
<#assign x=” Hello ${user}!”> true<o:p></o:p>
<o:p> </o:p>
同时也支持中文赋值,如:<o:p></o:p>
<#assign 语法><o:p></o:p>
java<o:p></o:p>
</#assign><o:p></o:p>
${语法}<o:p></o:p>
打印输出:<o:p></o:p>
java<o:p></o:p>
global<o:p></o:p>
语法
<#global name=value><o:p></o:p>
or<o:p></o:p>
<#global name1=value1 name2=value2 ... nameN=valueN><o:p></o:p>
or<o:p></o:p>
<#global name><o:p></o:p>
capture this<o:p></o:p>
</#global><o:p></o:p>
<o:p> </o:p>
全局赋值语法,利用这个语法给变量赋值,那么这个变量在所有的namespace[A1] 中是可见的,如果这个变量被当前的assign语法覆盖 如<#global x=2> <#assign x=1> 在当前页面里x=2将被隐藏,或者通过${.global.x}来访问<o:p></o:p>
<o:p> </o:p>
setting<o:p></o:p>
语法
<#setting name=value><o:p></o:p>
用来设置整个系统的一个环境<o:p></o:p>
locale<o:p></o:p>
number_format<o:p></o:p>
boolean_format<o:p></o:p>
date_format, time_format, datetime_format<o:p></o:p>
time_zone<o:p></o:p>
classic_compatible<o:p></o:p>
用例<o:p></o:p>
假如当前是匈牙利的设置,然后修改成美国<o:p></o:p>
${1.2}<o:p></o:p>
<#setting locale="en_US"><o:p></o:p>
${1.2} <o:p></o:p>
输出<o:p></o:p>
1,2<o:p></o:p>
1.2<o:p></o:p>
因为匈牙利是采用“,”作为十进制的分隔符,美国是用“.”<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
<o:p> </o:p>
macro, nested, return<o:p></o:p>
语法
<o:p> </o:p>
<#macro name param1 param2 ... paramN><o:p></o:p>
...<o:p></o:p>
<#nested loopvar1, loopvar2, ..., loopvarN><o:p></o:p>
...<o:p></o:p>
<#return><o:p></o:p>
...<o:p></o:p>
</#macro><o:p></o:p>
用例
<#macro test foo bar="Bar"[A2] baaz=-1><o:p></o:p>
Test text, and the params: ${foo}, ${bar}, ${baaz}<o:p></o:p>
</#macro><o:p></o:p>
<@test foo="a" bar="b" baaz=5*5-2/><o:p></o:p>
<@test foo="a" bar="b"/><o:p></o:p>
<@test foo="a" baaz=5*5-2/><o:p></o:p>
<@test foo="a"/> <o:p></o:p>
输出<o:p></o:p>
Test text, and the params: a, b, 23<o:p></o:p>
Test text, and the params: a, b, -1<o:p></o:p>
Test text, and the params: a, Bar, 23<o:p></o:p>
Test text, and the params: a, Bar, -1<o:p></o:p>
定义循环输出的宏<o:p></o:p>
<#macro list title items><o:p></o:p>
<p>${title?cap_first}:<o:p></o:p>
<ul><o:p></o:p>
<#list items as x><o:p></o:p>
<li>${x?cap_first}<o:p></o:p>
</#list><o:p></o:p>
</ul><o:p></o:p>
</#macro><o:p></o:p>
<@list items=["mouse", "elephant", "python"] title="Animals"/><o:p></o:p>
输出结果<o:p></o:p>
<p>Animals:<o:p></o:p>
<ul><o:p></o:p>
<li>Mouse<o:p></o:p>
<li>Elephant<o:p></o:p>
<li>Python<o:p></o:p>
</ul><o:p></o:p>
包含body的宏<o:p></o:p>
<#macro repeat count><o:p></o:p>
<#list 1..count as x><o:p></o:p>
<#nested x, x/2, x==count><o:p></o:p>
</#list><o:p></o:p>
</#macro><o:p></o:p>
<@repeat count=4 ; c halfc last><o:p></o:p>
${c}. ${halfc}<#if last> Last!</#if><o:p></o:p>
</@repeat> <o:p></o:p>
输出<o:p></o:p>
<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">1. 0.5</st1:chsdate><o:p></o:p>
2. 1<o:p></o:p>
<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">3. 1.5</st1:chsdate><o:p></o:p>
4. 2 Last!<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
<o:p> </o:p>
<o:p> </o:p>
t, lt, rt<o:p></o:p>
语法
<#t> 去掉左右空白和回车换行<o:p></o:p>
<o:p> </o:p>
<#lt>去掉左边空白和回车换行<o:p></o:p>
<o:p> </o:p>
<#rt>去掉右边空白和回车换行<o:p></o:p>
<o:p> </o:p>
<#nt>取消上面的效果<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
C一些常用方法或注意事项<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
表达式转换类<o:p></o:p>
${expression}计算expression并输出<o:p></o:p>
#{ expression }数字计算#{ expression ;format}安格式输出数字format为M和m<o:p></o:p>
M表示小数点后最多的位数,m表示小数点后最少的位数如#{121.2322;m<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2" unitname="m2">2M2</st1:chmetcnv>}输出121.23<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
<o:p> </o:p>
<o:p> </o:p>
数字循环<o:p></o:p>
1..5 表示从1到5,原型number..number<o:p></o:p>
对浮点取整数<o:p></o:p>
${123.23?int} 输出123
给变量默认值<o:p></o:p>
${var?default(“hello world<br>”)?html}如果var is null那么将会被hello world<br>替代<o:p></o:p>
<o:p> </o:p>
判断对象是不是null<o:p></o:p>
<#if mouse?exists><o:p></o:p>
Mouse found<o:p></o:p>
<#else><o:p></o:p>
也可以直接${mouse?if_exists})输出布尔形<o:p></o:p>
常用格式化日期<o:p></o:p>
openingTime必须是Date型,详细查看freemarker文档 Reference->build-in referece->build-in for date<o:p></o:p>
<o:p> </o:p>
${openingTime?date}<o:p></o:p>