freemarker 講義

1. 類型
支持的類型 數據模型實現 模型接口 操作 注意
標量
字符串 SimpleScalar TemplateScalarModel "Hello ${user}!",name[0] ,
r"${"test"}" Actually,the name of this interface should be TemplateStringModel
數字 SimpleNumber TemplateNumberModel ${1+1}
${x?string.currency}
${x?string("0.###")} int,long,float,double,byte,short.
number_format:number,computer,currency,
percent,0.###,0
布爾 TemplateBooleanModel.TURE
TemplateBooleanModel.FALSE TemplateBooleanModel ${boo?string} ${boo}錯誤
${boo?string}正確
日期 SimpleDate TemplateDateModel ${today?date}
${today?string(“MM/dd/yyyy”)}
${“04/27/2012”?date}
${“04/27/2012”?date(“MM/dd/yyyy”)} 1.支持java.util.Date,
java.sql.{Date,Time,Timestamp}
2.如果是java.util.Date,輸出日期時必須指定類型,?date,?time,?datetime,?string(“MM/dd/yyyy”)
3.可以通過全局配置date_format,time_format,datetime_format
容器
哈希表 SimpleHash TemplateHashModel {"name":"green mouse", "price":150}
user.name, user[“name”]
TemplateHashModelEx擴展了
Keys,values,size
可以實現了?keys,?values,?size
沒有remove,只能加,不能減
數據模型會被包裝成SimpleHash
序列 SimpleSequence TemplateSequenceModel ["foo", "bar", 123.45], 1..100
集 SimpleCollection TemplateCollectionModel
子程序
方法函數 自己定製的方法 TemplateMethodModel root.put("indexOf", new IndexOfMethod());

${indexOf("met", "something")} 1.BIMethod是【?】操作時所要實現功能的函數類,屬於私有類
2.避免共享,避免有狀態!

指令
系統只有兩個實現IncludePage和SimpleTagDir
ectiveModel.
可以自己定製 TemplateDirectiveModel root.put("upper", new com.example.
UpperDirective());

<@upper>
To upper words
</@upper> 1.可以通過IncludePage實現另外一個servlet的調用
2.避免共享,避免有狀態!
Java對象
Java bean StringModel
BeanModel TemplateScalarModel,
TemplateHashModel,
AdapterTemplateModel ${bean.getName()}
靜態對象 StaticModels TemplateHashModel ${statics["java.lang.System"].currentTimeMillis()} 有三個安全等級:
EXPOSE_ALL,EXPOSE_SAFE,
EXPOSE_PROPERTIES_ONLY,EXPOSE_NOTHING
2.內建函數
處理字符串的內建函數
substring
cap_first 首字母大寫
uncap_first
capitalize 每個單詞首字母大寫
upper_case 全部大寫
lower_case
chop_linebreak 切斷換行符
(如果在末尾沒有換行符的字符串,那麼可以換行,否則不改變字符串。)
date,time,datetime 日期,時間,時間日期
若日期字符串符合本地的日期格式 就無需傳入“MM/dd/yyyy”這樣的格式參數
<#assign test1 = "10/25/1995"?date("MM/dd/yyyy")>
<#assign test2 = "15:05:30"?time("HH:mm:ss")>
<#assign test3 = "1995-10-25 03:05 PM"?datetime("yyyy-MM-dd hh:mm a")>

<#assign test1 = "Oct 25, 1995"?date>
<#assign test2 = "3:05:30 PM"?time>
<#assign test3 = "Oct 25, 1995 03:05:00 PM"?datetime>

ends_with
html
HTML格式的轉義文本(xhtml xml)
 <用&lt替換;
 >用&gt替換;
 &用&amp替換;
 "用&quot替換;
${user?html}
可以使用escape指令來節約很多輸入,減少偶然錯誤的機會。

matches和groups
<#assign res = "aa/rx; ab/r;"?matches("(\\w[^/]+)/([^;]+);")>
<#list res as m>
- ${m} is ${m?groups[1]} per ${m?groups[2]}
</#list>

- aa/rx; is aa per rx
- ab/r; is ab per r
index_of
last_index_of
j_string Java語言規則的字符串轉義
<#assign beanName = 'The "foo" bean.'>
String BEAN_NAME = "${beanName?j_string}";
將會打印
String BEAN_NAME = "The \"foo\" bean.";
js_string JavaScript語言規則的字符串轉義
length
left_pad 距左邊 right_pad
[${"a"?left_pad(5)}]
[ a]
[${""?left_pad(5, "-")}]
[----a]
contains
number 字符串轉數字
replace
rtf 富文本
 \替換爲\\
 {替換爲\{
 }替換爲\}
url URL轉義
<#setting url_escaping_charset="UTF-8">
<#assign x = 'a/b c'>
${x?url}
a%2Fb%20c

<a href="foo.cgi?x=${x?url('utf-8')}">foo</a>

split
starts_with
trim 去掉字符串首尾的空格
word_list 詞列表
<#assign words = " a bcd, . 1-2-3"?word_list>
<#list words as word>[${word}]</#list>
將會輸出
[a][bcd,][.][1-2-3]
通用標記
i:大小寫不敏感:不區分同一個字母大小寫之間的差異。
f:僅僅是第一。也就是說,替換/查找等,只是第一次出現的東西。
r:查找的子串是正則表達式。

<#assign s = 'foo bAr baar'>
${s?replace('ba', 'XY')}
i: ${s?replace('ba', 'XY', 'i')}
if: ${s?replace('ba', 'XY', 'if')}
r: ${s?replace('ba*', 'XY', 'r')}
ri: ${s?replace('ba*', 'XY', 'ri')}
rif: ${s?replace('ba*', 'XY', 'rif')}
輸出爲:
foo bAr XYar
i: foo XYr XYar
if: foo XYr baar
r: foo XYAr XYr
ri: foo XYr XYr
rif: foo XYr baar
處理數字的內建函數
c 數字轉字符
避免輸出由於當前數字格式設置,本地化
${x?c}
string(當用作是數值類型時) 數字轉字符串
$ {x?string}
${x?string.number}
${x?string.currency}
${x?string.percent}
${x?string.computer}
42
42
$42.00
4,200%
42
round,floor,ceiling 數字的舍入處理
floor:向負無窮進位
ceiling:向正無窮進位
處理日期的內建函數
string(當用作日期值時)日期轉字符串
date,time,datetime (當使用日期值時)
iso_utc,iso_local,iso_utc_nz,iso_local_nz,iso_utc_m,iso_utc_m_nz內建函數族
utc,local:國際統一和本地當前時間
nz:是否顯示時區偏移
處理布爾值的內建函數
string(當被用作是布爾值時) 轉換布爾值爲字符串
foo?string("yes", "no")
處理序列的內建函數
first 第一個變量
last 最後一個變量
seq_contanis 序列包含…
seq_index_of 第一次出現…時的位置
${names?seq_index_of("Joe", 0)}從第一個位子開始找
seq_last_index_of 最後一次出現..的位置
names?seq_last_index_of("Joe", 0)從第一個位置往前找
size 序列大小
sort 排序
可以字符串,數字,日期,布爾排序
sort_by 以…來排序
<#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 name.last:
<#list members?sort_by(['name', 'last']) as m>
- ${m.name.last}, ${m.name.first}: ${m.age} years old
</#list>
如果想按降序來排列,後面再加?reverse
reverse 反轉序列
chunk 區塊
<#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>
輸出:
a b c d
e f g h
i j - -
處理哈希表的內建函數(並不是所有的hash表都支持以下兩種)
keys
values
3.模板語法及指令(宏)
if
<#if x == 1>
x is 1
<#if y == 1>
and y is 1 too
<#elseif y==2>
but y is not
</#if>
<#else>
x is not 1
<#if (y < 0)>
and y is less than 0
</#if>
</#if>
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>
List
<#list seq as x>
${x}
<#if x = "spring"><#break></#if>
</#list>
Include
<#include path options>
Option 選項只有兩個, encoding和parse(如果爲false,當成普通文本)
<#include "/common/navbar.html" parse=false encoding="Shift_JIS">
本地化查找:
加載模板時,經常用本
地化環境匹配瀏覽器請求Web頁面的語言偏好來請求模板。
 footer_en_US.ftl
 footer_en.ftl
 footer.ftl
import
<#import "/libs/mylib.ftl" as my>
<@my.copyright date="1999-2002"/>
可以通過configuration的addAutoImport做通用的引入操作
noparse
<#noparse>
<#list animals as being>
<tr><td>${being.name}<td>${being.price} Euros
</#list>
</#noparse>
不解析,作爲普通文本
compress
<#assign x = " moo \n\n ">
(<#compress>
1 2 3 4 5
${moo}
test only
I said, test only
</#compress>)
輸出爲:
(1 2 3 4 5
moo
test only
I said, test only)
需要和剝離空白區分,compress會對生成後的文本進行壓縮,比setWhitespaceStripping強勢
escape,noescape
<#escape x as x?html>
From: ${mailMessage.From}
Subject: ${mailMessage.Subject}
<#noescape>Message: ${mailMessage.htmlFormattedBody}</#noescape>
...
</#escape>
Assign
多個定義
<#assign
seasons = ["winter", "spring", "summer", "autumn"]
test = test + 1
>
捕捉它的開始標記和結束標記中間生成的輸出,成爲它的值
<#macro myMacro>foo</#macro>
<#assign x>
<#list 1..3 as n>
${n} <@myMacro />
</#list>
</#assign>
Number of words: ${x?word_list?size}
${x}
global 指令
<#global name=value> 所有命名空間中都可以看到
<#setting name=value>
local 指令
<#local name=value>
僅僅在宏和方法的內部定義纔會有作用。
setting 指令
<#setting name=value>
Locale
number_format,
boolean_format
date_format,time_format,datetime_format
time_zone
url_escaping_charset
classic_compatible
用戶自定義指令
<@list items=["mouse", "elephant", "python"] title="Animals"/>
...
<#macro list title items>
<p>${title?cap_first}:
<ul>
<#list items as x>
<li>${x?cap_first}
</#list>
</ul>
</#macro>
輸出爲:
<p>Animals:
<ul>
<li>Mouse
<li>Elephant
<li>Python
</ul>
位置參數傳遞現在僅僅支持宏定義
macro,nested,return 指令
<#macro name param1 param2 ... paramN>
...
<#nested loopvar1, loopvar2, ..., loopvarN>
...
<#return>
...
</#macro>

參數省略示例:
<#macro test foo bar="Bar" baaz=-1>
Test text, and the params: ${foo}, ${bar}, ${baaz}
</#macro>

macro示例:可變的參數數量:
<#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"/>
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>
function,return 指令
<#function name param1 param2 ... paramN>
...
<#return returnValue>
...
</#function>
示例:
<#function avg x y>
<#return (x + y) / 2>
</#function>
${avg(10, 20)}
同樣支持可變的參數數量
stop 指令
<#stop>

<#stop reason>
拋出StopException
ftl 指令
<#ftl param1=value1param2=value2…paramN=valueN>
ftl指令必須放在ftl文件的最上面。
一些設置(編碼方式,空白剝離等)在這裏給定的話就有最高的優先級,也就是說,它們直接作用於模板而不管其他任何FreeMarker配置的設置。
t,lt,rt 指令
t(整體削減):忽略本行中首和尾的所有空白。
lt(左側削減):忽略本行中首部所有的空白。
rt(右側削減):忽略本行中尾部所有的空白。
示例:
1 <#t>
2<#t>
3<#lt>
4
5<#rt>
6
輸出:
1 23
4
5 6
attempt,recover 指令
<#attempt>
attempt block
<#recover>
recover block(代替出錯內容)
</#attempt>
自定義方法和指令
Java程序員可以使用TemplateMethodModel接口在Java代碼中實現自定義方法。
TemplateModel exec(java.util.List arguments)
Java程序員可以使用TemplateDirectiveModel接口在Java代碼中實現自定義指令。
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body)
4.配置
配置信息可以被想象成3層(Configuration,Template,Environment),他們都實現configurable抽象
Configuration層:原則上設置配置信息時使用Configuration對象的setter方法
注意:在真正使用Configuration對象(通常在初始化應用程序時)之前來配置它,後面必須將其視爲只讀的對象。
Template層:這裏不需要設置配置信息。應該在Template對象第一次被使用前就設置配置信息,然後就將Template對象視爲是隻讀的。
Environment層:這裏有兩種配置方法:
1. Java api
env.setLocale(java.util.Locale.ITALY);
env.setNumberFormat("0.####");
2. 在模板中直接使用指令
<#setting locale="it_IT">
<#setting number_format="0.####">

所有配置項可以到configurable或api文檔裏面查

5.內部重要的類
Configuration
Freemarker api的入口
配置模板的加載器和緩存(setDirectoryForTemplateLoading, setServletContextForTemplateLoading, setClassForTemplateLoading)
管理共享變量
配置項
Template
通過FMParser創建rootElement
創建運行環境(environment)
配置項
Environment
執行模板(process),遍歷模板中的rootElement
配置項
DefaultObjectWrapper
功能已經足夠,繼承了BeansWrapper的封裝。
數據模型中的Collection和Map不被允許修改。可以通過一個java bean來實現
TemplateCache
通過templateLoader和storage來管理系統中的所有模板

CacheStorage
softStorage strongStorage MRUStorage

TemplateLoader(WebappTemplateLoader, FileTemplateLoader,ClassTemplateLoader)
功能:獲取對象及修改時間
設置更新延遲,默認5秒(目前19樓主幹上的是0)。類加載器不會注意到模板的更新。
在實際運行的環境中,類加載機制是首選用來加載模板的方法.。比從文件系統的特定目錄位置加載安全而且簡單
MultiTemplateLoader多加載器

TemplateElement(MixedContent,TextBlock,DollarVariable…)
模板(樹)節點
執行輸出(accept),TextBlock示例:
public void accept(Environment env)
throws IOException
{
env.getOut().write(text);
}
TemplateModel
所有能放到數據模型的對象都需要實現該接口

Expression
大部分的TemplateElement會有Expression實例作爲成員對象。Expression也是一個樹結構。
通過暴露getStringValue(env)和_getAsTemplateModel(env)來實現樹的遍歷

BuiltIn
the ? operator used to get the functionality of built-in unary operators
可以通過該類查找freemarker裏所有的內建函數

FMParser
This class is generated by JavaCC from a grammar file
JavaCC(Java Compiler Compiler)是一個用JAVA開發的語法分析生成器。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章