Freemarker詳解

A概念

最常用的概念
1、 scalars:存儲單值

字符串:簡單文本由單或雙引號括起來。
數字:直接使用數值。
日期:通常從數據模型獲得
布爾值:true或false,通常在<#if …>標記中使用

 
2、 hashes:充當其它對象的容器,每個都關聯一個唯一的查詢名字

具有一個唯一的查詢名字和他包含的每個變量相關聯。

 
3、 sequences:充當其它對象的容器,按次序訪問

使用數字和他包含的每個變量相關聯。索引值從0開始。

 
4、 集合變量:

除了無法訪問它的大小和不能使用索引來獲得它的子變量:集合可以看作只能由<#list...>指令使用的受限sequences。

 
5、 方法:通過傳遞的參數進行計算,以新對象返回結果

方法變量通常是基於給出的參數計算值在數據模型中定義。

 
6、 用戶自定義FTL指令:宏和變換器

 
7、 節點

節點變量表示爲樹型結構中的一個節點,通常在XML處理中使用。
 
在模板裏對sequenceshashes初始化

sequences 

    1. [“you”,”me”,”he”] 2. 1..100 3. [ {“Akey”:”Avalue”},{“Akey1”:”Avalue1”}, {“Bkey”:”Bvalue”},{“Bkey1”:”Bvalue1”}, ]     hashes      {“you”:”a”,”me”:”b”,”he”:”c”}    

註釋標誌

<#--

 
這裏是註釋
-->
舊版本的freemarker採用的是<#comment> 註釋 </#comment>方法
 
sequences內置方法
sequence?first
返回sequence的第一個值;前提條件sequence不能是null
sequence?last
       返回sequence最後一個值
sequence?reverse
       反轉sequence的值
sequence?size
       返回sequence的大小
sequence?sort
       對sequence按裏面的對象toString()的結果進行排序
sequence?sort_by(value)
對sequence 按裏面的對象的屬性value進行排序
如: sequence裏面放入的是10 個user對象,user對象裏面包含name,age等屬性
sequence?sort_by(name) 表示所有的user按user.name進行排序
hashes內置方法
hash?keys
       返回hash裏的所有keys, 返回結果類型sequence
hash?values
       返回hash裏的所有value, 返回結果類型sequence
 
 
模板
使用FTL(freeMarker模板語言)編寫

組成部分

一、整體結構

1、註釋:<#--註釋內容-->,不會輸出。

2、文本:直接輸出。

3、interpolation:由 ${var} 或 #{var} 限定,由計算值代替輸出。

4、FTL標記



二.表達式

1、直接指定值


1-1、字符串:
由雙引號或單引號括起來的字符串,其中的特殊字符(如' " \等)需要轉義。


1-2、raw字符串:
有一種特殊的字符串稱爲raw字符串,被認爲是純文本,其中的\和{等不具有特殊含義,該類字符串在引號前面加r,下面是一個例子:
${r"/${data}"year""}屏幕輸出結果爲:/${data}"year"


轉義    含義
序列   

 
\"  雙引號(u0022)
 
\'  單引號(u0027)
 
\\  反斜槓(u005C)
 
\n  換行(u000A)
 
\r  Return (u000D)
 
\t  Tab (u0009)
 
\b  Backspace (u0008)
 
\f  Form feed (u000C)
 
\l  <
 
\g  >
 
\a  &
 
\{  {
 
\xCode  4位16進制Unicode代碼
 
1-3、數字:直接輸入,不需要引號

1)、精度數字使用“.”分隔,不能使用分組符號
2)
、目前版本不支持科學計數法,所以“1E3”是錯誤的
3)、不能省略小數點前面的0,所以“.5”是錯誤的
4)、數字8、+8、08和8.00都是相同的

1-4、布爾值:true和false,不使用引號

1-5、序列:由逗號分隔的子變量列表,由[]方括號限定。
1)、子變量列表可以是表達式
2)、可以使用數字範圍定義數字序列,不需要方括號限定,例如2..5等同於[2, 3, 4, 5],但是更有效率,可以定義反遞增範圍如:5..2。

1-6、散列(hash)
1)、由逗號分隔的鍵/值列表,由{}大括號限定,鍵和值之間用冒號分隔,如:{"key1":valu1,"key2":"character string"....}
2)、鍵和值都是表達式,但是鍵必須是字符串。

2、獲取變量:

2-1、頂層變量
:${變量名}

變量名只能是字母、數字、下劃線、$、#、@ 的組合,且不能以數字開頭。

2-2、散列:有兩種方法

1)、點語法:變量名字和頂層變量的名字受同樣的限制
2)、方括號語法:變量名字無限制,可以是任意的表達式的結果
book.author.name
book.author.["name"]
book["author"].name
book["author"]["name"]
以上是等價的。

2-3、序列:使用散列的方括號語法獲取變量,方括號中的表達式結果必須爲數字。注意:第一個項目的索引爲0。可以使用
[startindex..endindex]語法獲取序列片段。

2-4、特殊變量:FreeMarker內定義變量,使用.variablename語法訪問。

3、字符串操作

3-1、interpolation
:使用${}或#{}在文本部分插入表達式的值,例如:

${"hello${username}!"}
${"${username}${username}${username}"}

也可以使用+來獲得同樣的結果:
${"hello"+username+"!"}
${username+username+username}

注意:${}只能用於文本部分而不能出現於標記內。

<#if ${user.login}>或<#if "${user.login}">都是錯誤的;
<#if user.login>是正確的。
本例中user.login的值必須是布爾類型。

3-2、子串
舉例說明:假如user的值爲"Big Joe"
${user[0]}${user[4]}結果是:BJ
${user[1..4]}結果是:ig J

4、序列操作

4-1、連接操作
:可以使用+來操作,例如:
["title","author"]+["month","day"]

5、散列操作
5-1、連接操作
:可以使用+來操作,如果有相同的KEY,則右邊的值會替代左邊的值,例如:
{"title":散列,"author":"emma"}+{"month":5,"day":5}+{"month":6}結果month的值就是6。

6、算術運算

6-1、操作符
:+、-、*、/、%
除+號以外的其他操作符兩邊的數據,必須都是數字類型。
如果+號操作符一邊有一個字符型數據,會自動將另一邊的數據轉換爲字符型數據,運算結果爲字符型數據。

6-2、比較操作符:
1}、=
2}、==
3}、!=
4}、<
5}、<=
6}、>
7}、>=
1-3的操作符,兩邊的數據類型必須相同,否則會產生錯誤
4-7的操作符,對於日期和數字可以使用,字符串不可以使用。

注意:
1}、FreeMarker是精確比較,所以"x" "x " "X"是不等的。
2}、因爲<和>對FTL來說是開始和結束標記,所以,可以用兩種方法來避免這種情況:
一種是使用括號<#if (a<b)>
另一是使用替代輸出,對應如下:
<  lt
<= lte
>  gt
>= gte

6-3、邏輯操作符:只能用於布爾值,否則會出現錯誤。

&&(and)與運算
||(or)或運算
!(not)非運算

6-4、內建函數:使用方法類似於訪問散列的子變量,只是使用?代替.例如:${test?upper_case?html}

常用的內建函數列舉如下:

1}、字符串使用:

html:對字符串進行HTML編碼
cap_first:字符串第一個字母大寫
lower_first:字符串第一個字母小寫
upper_case:將字符串轉換成大寫
trim:去掉字符前後的空白字符

2)、序列使用:
size:獲得序列中元素的數目

3)、數字使用:
int:取得數字的整數部分

7、操作符的優先順序:


後綴:[subbarName][subStringRange].(mathodParams)
一元:+expr、-expr、! (not)
內建:?
乘法:*、/、%
加法:+、-
關係:<、<=、>、>= (lt、lte、gt、gte)
相等:=、==、!=
邏輯與:&& (and)
邏輯或:|| (or)
數字範圍:..

四、interpolation

inperpolation只能用於文本,有兩種類型:通用interpolation及數字interpolation

1、通用interpolation

如${expr}

1-1、插入字符串值:直接輸出表達式結果。
1-2、插入數字值:根據缺省格式(由setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string來格式化單個interpolation

如:
<#setting number_format="currency" />
<#assign answer=42 />
${answer}  <#-- ¥42.00 -->
${answer?string}  <#-- ¥42.00 -->
${answer?string.number}  <#-- 42 -->
${answer?string.currency}  <#-- ¥42.00 -->
${answer?string.percent}  <#-- 42,00% -->

1-3、插入日期值:根據缺省格式(由setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string來格式化單個interpolation

如:

${lastupdata?string("yyyy-MM-dd HH:mm:ss zzzz")}  <#-- 2003-04-08 21:24:44 Pacific Daylight Time -->
${lastupdata?string("EEE,MMM d, ''yy")}  <#-- tue,Apr 8, '03 -->
${lastupdata?string("EEEE,MMMM dd, yyyy,hh:mm:ss a '('zzz')'")}  <#-- Tuesday,April 08, 2003, 09:24:44 PM (PDT)-->

1-4、插入布爾值:根據缺省格式(由setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string來格式化單個interpolation

如:
<#assign foo=ture />
${foo?string("yes","no")} <#-- yes -->

2、數字interpolation:

有兩種形式:
1)、#{expr}
2)、#{expr;format}:format可以用來格式化數字,format可以是如下:
mX:小數部分最小X位
MX:小數部分最大X位

例如:
<#assign x=2.582 />
<#assign y=4 />
#{x;M2} <#-- 2.58 -->
#{y;M2} <#-- 4 -->
#{x;m1} <#-- 2.582 -->
#{y;m1} <#-- 4.0 -->
#{x;m1M2} <#-- 2.58 -->
#{y;m1M2} <#-- 4.0 -->
 
 


宏和變換器變量是兩種不同類型的用戶自定義指令,他們的區別是:

宏可以在模板中用macro指令來定義
變換器是在模板外由程序定義

1、宏:和某個變量關聯的模板片段,以便在模板中通過用戶自定義指令使用該變量
1-1、基本用法:

例如:
<#macro greet>
<font size="+2"> Hello JOE!
</#macro>


使用時:
<@greet></@greet>
如果沒有體內容也可以用
<@greet />

1-2、變量:

1)、可以在宏定義之後定義參數,宏參數是局部變量,只在宏定義中有效。如:

<#macro greet person>
<font size="+2"> Hello ${person}!
</#macro>
使用時:
<@greet person="emma"> and <@greet person="LEO">
輸出爲:
<font size="+2"> Hello emma!
<font size="+2"> Hello LEO!

注意:宏的參數是FTL表達式,所以,person=emma和上面的例子中具有不同的意義,這意味着將變量emma的值傳給person,這個值可能是任意一種數據類型,甚至是一個複雜的表達式。


宏可以有多個參數,使用時參數的次序是無關的,但是隻能使用宏中定義的參數,並且對所有參數賦值。如:
<#macro greet person color>
<font size="+2" color="${color}"> Hello ${person}!
</#macro>

使用時:
<@greet color="black" person="emma" />正確
<@greet person="emma" />錯誤,color沒有賦值,此時,如果在定義宏時爲color定義缺省值<#macro greet person color="black">這樣的話,這個使用方法就是正確的。
<@greet color="black" person="emma" bgcolor="yellow" />錯誤,宏greet定義中未指定bgcolor這個參數



2、嵌套內容:

2-1、自定義指令可以有嵌套內容
,使用<#nested>指令,執行自定義指令開始和結束標記之間的模板片段。例如:
<#macro greet>


<#nested>
 


</#macro>


<@greet>hello Emma!</@greet>

輸出爲

hello Emma!



2-2、<#nested>指令可以被多次調用,例如
<#macro greet>


<#nested>
<#nested>
<#nested>
<#nested>
 


</#macro>

<@greet>hello Emma!</@greet>

輸出爲


hello Emma!
hello Emma!
hello Emma!
hello Emma!
 



2-3、嵌套的內容可以是有效的FTL,例如:
<#macro welcome>


<#nested>
 


</#macro>

<#macro greet person color="black">
<font size="+2" color="${color}"> Hello ${person}!
</#macro>

<@welcome>
<@greet person="Emma" color="red" />
<@greet person="Andrew" />
<@greet person="Peter" />
</@welcome>

輸出爲:


<font size="+2" color="red"> Hello Emma!
<font size="+2" color="black"> Hello Andrew!
<font size="+2" color="black"> Hello Peter!
 



2-4、宏定義中的局部變量對嵌套內容是不可見的,例如:

<#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:???

2-5、在宏定義中使用循環變量,通常用來重複嵌套內容,基本用法爲:作爲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.5
2. 1
3. 1.5
4. 2last!

注意:指定循環變量的數目和用戶定義指令開始標記指定的不同不會有問題
調用時,少指定循環變量,多指定的值會不見
調用時,多指定循環變量,多餘的循環變量不會被創建

二、在模板中定義變量

1、在模板中定義的變量有三種類型


1-1、plain變量:可以在模板的任何地方訪問,包括使用include指令插入的模板,使用assign指令創建和替換。
1-2、局部變量:在宏定義體中有效,使用local指令創建和替換。
1-3、循環變量:只能存在於指令的嵌套內容,由指令(如list)自動創建。

注意:
1)、宏的參數是局部變量,不是循環變量。
2)、局部變量隱藏同名的plain變量
3)、循環變量隱藏同名的plain變量和局部變量。

例如:

<#assign x="plain">
1. ${x} <#-- plain -->

<@test />

6. ${x}
<#list ["loop"] as x>
7. ${x} <#-- loop -->
<#assign x="plain2">
8. ${x} <#-- loop -->
</#list>
9. ${x} <#-- plain2 -->

<#macro test>
2. ${x} <#-- plain -->
<#local x="local">
3. ${x} <#-- local -->
<#list ["loop"] as x>
4. ${x} <#-- loop -->
</#list>
5. ${x} <#-- local -->
</#macro>

4)、內部循環變量隱藏同名的外部循環變量

<#list ["loop1"] as x>
${x} <#-- loop1 -->
<#list ["loop2"] as x>
${x} <#-- loop2 -->
<#list ["loop3"] as x>
${x} <#-- loop3 -->
</#list>
${x} <#-- loop2 -->
</#list>
${x} <#-- loop1 -->
</#list>

5)、模板中的變量會隱藏數據模型中的同名變量,如果需訪問數據模型中的變量,使用特殊變量global。

例如:
假設數據模型中的user值爲Emma
<#assign user="Man">
${user} <#-- Man -->
${.global.user} <#-- Emma -->
 
macro, nested, return
語法
 

<#macro name param1 param2 ... paramN>

   ...  <#nested loopvar1, loopvar2, ..., loopvarN>  ...  <#return>  ... </#macro>

用例

<#macro test foo bar="Bar"[A1] baaz=-1>  Test text, and the params: ${foo}, ${bar}, ${baaz} </#macro> <@test foo="a" bar="b" baaz=5*5-2/> <@test foo="a" bar="b"/> <@test foo="a" baaz=5*5-2/>

<@test foo="a"/> 

 
輸出

 Test text, and the params: a, b, 23

   Test text, and the params: a, b, -1  Test text, and the params: a, Bar, 23

 Test text, and the params: a, Bar, -1

 
定義循環輸出的宏

<#macro list title items>

   

${title?cap_first}:

 

 <ul>     <#list items as x>       <li>${x?cap_first}     </#list>   </#macro>

<@list items=["mouse", "elephant", "python"] title="Animals"/>

 

輸出結果 

 

Animals:

 

 

 
包含body的宏

<#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.5

   2. 1  3. 1.5

 4. 2 Last!

 
 
 
t, lt, rt
語法

<#t> 去掉左右空白和回車換行

    <#lt>去掉左邊空白和回車換行   <#rt>去掉右邊空白和回車換行   <#nt>取消上面的效果  

 

 
 
B指令
freemarker指令有兩種:
1、預定義指令:引用方式爲<#指令名稱>
2、用戶定義指令:引用方式爲<@指令名稱>,引用用戶定義指令時須將#換爲@。
注意:如果使用不存在的指令,FreeMarker不會使用模板輸出,而是產生一個錯誤消息。

freemarker指令由FTL標記來引用,FTL標記和HTML標記類似,名字前加#來加以區分。如HTML標記的形式爲<h1></h1>則FTL標記的形式是<#list></#list>(此處h1標記和list指令沒有任何功能上的對應關係,只是做爲說明使用一下)。

有三種FTL標記:
1)、開始標記:<#指令名稱>
2)、結束標記:</#指令名稱>
3)、空標記:<#指令名稱/>

注意:

1) FTL會忽略標記之中的空格,但是,<#和指令 與 </#和指令 之間不能有空格。
2) FTL標記不能夠交叉,必須合理嵌套。每個開始標記對應一個結束標記,層層嵌套。 如:
<#list>
<li>
${數據}
<#if 變量>

game over!


</#if>

</#list>

注意事項:
1)、FTL對大小寫敏感。所以使用的標記及interpolation要注意大小寫。name與NAME就是不同的對象。<#list>是正確的標記,而<#List>則不是。
2)、interpolation只能在文本部分使用,不能位於FTL標記內。如<#if ${var}>是錯誤的,正確的方法是:<#if var>,而且此處var必須爲布爾值。
3)、FTL標記不能位於另一個FTL標記內部,註釋例外。註釋可以位於標記及interpolation內部。


 
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>

 
 

We have these animals:

<table border=1>
 <tr><th>Name<th>Price
 <#list animals as being>
 <tr>
    <td>
      <#if being.size = "large"></#if></#if>
      ${being.name}
      <#if being.size = "large">
    <td>${being.price} Euros
 </#list>
</table>
<#if user = "Big Joe">
 It is Big Joe
</#if>
<#if user != "Big Joe">
 It is not Big Joe
</#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 輸出d

 
 
list, 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. autumn      
include
語法
<#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>

Yeah.

<#include "/common/copyright.ftl" encoding=”GBK”> 

 
輸出結果

<h1>Some test</h1>

 

Yeah.

<html>

 
<head>
 <title>Test page</title>
</head>
<body>
 <h1>Test page</h1>
 

Blah blah...

<#include "/copyright_footer.html">
</body>
</html> 

 

 

 

 
Import
語法

<#import path as hash>

  類似於java裏的import,它導入文件,然後就可以在當前文件裏使用被導入文件裏的宏組件  
用例

 

 
假設mylib.ftl裏定義了宏copyright那麼我們在其他模板頁面裏可以這樣使用

<#import "/libs/mylib.ftl" as my>

   

<@my.copyright date="1999-2002"/>

 
 
"my"在freemarker裏被稱作namespace

 

 
compress
語法
<#compress>  ...

</#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) 

 
escape, noescape
語法

<#escape identifier as expression>

   ...  <#noescape>...</#noescape>  ... </#escape>
用例
主要使用在相似的字符串變量輸出,比如某一個模塊的所有字符串輸出都必須是html安全的,這個時候就可以使用該表達式 <#escape x as x?html>  First name: ${firstName}  <#noescape>Last name: ${lastName}</#noescape>  Maiden name: ${maidenName} </#escape> 相同表達式    First name: ${firstName?html}  Last name: ${lastName }  Maiden name: ${maidenName?html}
assign
語法
<#assign name=value> or <#assign name1=value1 name2=value2 ... nameN=valueN> or <#assign same as above... in namespacehash> or <#assign name>  capture this </#assign> or <#assign name in namespacehash>  capture this </#assign>
用例
生成變量,並且給變量賦值 給seasons賦予序列值 <#assign seasons = ["winter", "spring", "summer", "autumn"]>   給變量test加1 <#assign test = test + 1>   給my namespage 賦予一個變量bgColor,下面可以通過my.bgColor來訪問這個變量 <#import "/mylib.ftl" as my> <#assign bgColor="red" in my>   將一段輸出的文本作爲變量保存在x裏 下面的陰影部分輸出的文本將被賦值給x <#assign x>  <#list 1..3 as n>     ${n} <@myMacro />  </#list> </#assign> Number of words: ${x?word_list?size} ${x}   <#assign x>Hello ${user}!</#assign>     error <#assign x=” Hello ${user}!”>         true   同時也支持中文賦值,如: <#assign 語法>  java </#assign> ${語法} 打印輸出: java
global
語法
<#global name=value> or <#global name1=value1 name2=value2 ... nameN=valueN> or <#global name>  capture this </#global>

 

 
 
setting
語法

<#setting name=value>

 

用來設置整個系統的一個環境

 
locale
number_format
boolean_format
date_format, time_format, datetime_format
time_zone
classic_compatible
用例
假如當前是匈牙利的設置,然後修改成美國

${1.2}

  <#setting locale="en_US"> ${1.2} 

輸出

 

1,2

  1.2

因爲匈牙利是採用“,”作爲十進制的分隔符,美國是用“.”

 
 
 
 
C一些常用方法或注意事項
 
 
表達式轉換類
${expression}計算expression並輸出
#{ expression }數字計算#{ expression ;format}安格式輸出數字format爲M和m
M表示小數點後最多的位數,m表示小數點後最少的位數如#{121.2322;m2M2}輸出121.23
 
 
 
 
數字循環
1..5 表示從1到5,原型number..number
對浮點取整數
${123.23?int} 輸出123
給變量默認值
${var?default(“hello world<br>”)?html}如果var is null那麼將會被hello world<br>替代
 
判斷對象是不是null

    <#if mouse?exists>

       Mouse found <#else> 也可以直接${mouse?if_exists})輸出布爾形
常用格式化日期
 openingTime必須是Date型,詳細查看freemarker文檔 Reference->build-in referece->build-in for date   ${openingTime?date} ${openingTime?date_time} ${openingTime?time}  
添加全局共享變量數據模型
在代碼裏的實現     cfg = Configuration.getDefaultConfiguration(); cfg.setSharedVariable("global", "you good"); 頁面實現可以通過global指令,具體查看指令裏的global部分
直接調用java對象的方法
${object.methed(args)}   
字符串處理(內置方法)
html安全輸出

“abc<table>sdfsf”?html

 
返回安全的html輸出,替換掉html代碼
xml安全輸出
var?xml  
substring的用法

<#assign user=”hello jeen”>

  ${user[0]}${user[4]} ${user[1..4]} 輸出 : ho ello 
類似String.split的用法
 “abc;def;ghi”?split(“;”)返回sequence
將字符串按空格轉化成sequence,然後取sequence的長度

           var?word_list 效果同 var?split(“ ”)

 

         var?word_list?size

   
取得字符串長度
var?length  
大寫輸出字符

var?upper_case

 

 

 
小寫輸出字符
var?lower_case  
首字符大寫
var?cap_first  
首字符小寫
var?uncap_first  
去掉字符串前後空格
var?trim  
每個單詞的首字符大寫
var?capitalize  
類似String.indexof:
         “babcdabcd”?index_of(“abc”) 返回1          “babcdabcd”?index_of(“abc”,2) 返回5
類似String.lastIndexOf
         last_index_of和String.lastIndexOf類似,同上  
下面兩個可能在代碼生成的時候使用(在引號前加”\”)
j_string: 在字符串引號前加”\”         <#assign beanName = 'The "foo" bean.'>         String BEAN_NAME = "${beanName?j_string}"; 打印輸出:         String BEAN_NAME = "The \"foo\" bean."; js_string:          <#assign user = "Big Joe's \"right hand\"."> <script>  alert("Welcome ${user}!"); </script>  打印輸出         alert("Welcome Big Joe\'s \"right hand\"!");  
替換字符串 replace
${s?replace(‘ba’, ‘XY’ )} ${s?replace(‘ba’, ‘XY’ , ‘規則參數’)}將s裏的所有的ba替換成xy 規則參數包含:i r m s c f具體含義如下:

·         i: 大小寫不區分.

 
·         f: 只替換第一個出現被替換字符串的字符串
·         r:  XY是正則表達式
·         m: Multi-line mode for regular expressions. In multi-line mode the expressions ^ and $ match just after or just before, respectively, a line terminator or the end of the string. By default these expressions only match at the beginning and the end of the entire string.
·         s: Enables dotall mode for regular expressions (same as Perl singe-line mode). In dotall mode, the expression . matches any character, including a line terminator. By default this expression does not match line terminators.
·         c: Permits whitespace and comments in regular expressions.

 

   
D freemarkerweb開發中注意事項

freemarker與webwork整合

 
web中常用的幾個對象
Freemarker的ftl文件中直接使用內部對象:
${Request ["a"]}
${RequestParameters["a"]}
${Session ["a"]}
${Application ["a"]}
${JspTaglibs ["a"]}
 
與webwork整合之後 通過配置的servlet 已經把request,session等對象置入了數據模型中
在view中存在下面的對象
 我們可以在ftl中${req}來打印req對象
  • req - the current HttpServletRequest
  • res - the current HttpServletResponse
  • stack - the current OgnlValueStack
  • ognl - the OgnlTool instance
  • webwork - an instance of FreemarkerWebWorkUtil
  • action - the current WebWork action
  • exception - optional the Exception instance, if the view is a JSP exception or Servlet exception view
view中值的搜索順序
${name}將會以下面的順序查找name值
  • freemarker variables
  • value stack
  • request attributes
  • session attributes
  • servlet context attributes
在模板裏ftl裏使用標籤
注意,如果標籤的屬性值是數字,那麼必須採用nubmer=123方式給屬性賦值
JSP頁面

<%@page contentType="text/html;charset=ISO-8859-2" language="java"%>

  <%@taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> <%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>   <html>  <body>     <h1><bean:message key="welcome.title"/></h1>     <html:errors/>     <html:form action="/query">       Keyword: <html:text property="keyword"/><br>       Exclude: <html:text property="exclude"/><br>       <html:submit value="Send"/>     </html:form>  </body> </html> 

模板ftl頁面

 

<#assign html=JspTaglibs["/WEB-INF/struts-html.tld"]>

  <#assign bean=JspTaglibs["/WEB-INF/struts-bean.tld"]>   <html>  <body>     <h1><@bean.message key="welcome.title"/></h1>     <@html.errors/>     <@html.form action="/query">       Keyword: <@html.text property="keyword"/><br>       Exclude: <@html.text property="exclude"/><br>       <@html.submit value="Send"/>     </@html.form>  </body> </html> 

 

 
 
如何初始化共享變量
1. 初始化全局共享數據模型
freemark在web上使用的時候對共享數據的初始化支持的不夠,不能在配置初始化的時候實現,而必須通過ftl文件來初始化全局變量。這是不能滿主需求的,我們需要在servlet init的時候留出一個接口來初始化系統的共享數據
具體到和webwork整合,因爲本身webwork提供了整合servlet,如果要增加全局共享變量,可以通過修改com.opensymphony.webwork.views.freemarker.FreemarkerServlet來實現,我們可以在這個servlet初始化的時候來初始化全局共享變量
與webwork整合配置
配置web.xml
<servlet>
    <servlet-name>freemarker</servlet-name>
    <servlet-class>com.opensymphony.webwork.views.freemarker.FreemarkerServlet</servlet-class>
    <init-param>
      <param-name>TemplatePath</param-name>
<param-value>/</param-value>
<!—模板載入文件夾,這裏相對context root,遞歸獲取該文件夾下的所有模板-->
    </init-param>
    <init-param>
      <param-name>NoCache</param-name> <!—是否對模板緩存-->
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>ContentType</param-name>
      <param-value>text/html</param-value>
    </init-param>
    <init-param>
<param-name>template_update_delay</param-name>
<!—模板更新時間,0表示每次都更新,這個適合開發時候-->
      <param-value>0</param-value>
    </init-param>
    <init-param>
      <param-name>default_encoding</param-name>
      <param-value>GBK</param-value>
    </init-param>
    <init-param>
      <param-name>number_format</param-name>
      <param-value>0.##########</param-value><!—數字顯示格式-->
    </init-param>
    <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
    <servlet-name>freemarker</servlet-name>
    <url-pattern>*.ftl</url-pattern>
 </servlet-mapping>
 
E高級方法
自定義方法

${timer("yyyy-MM-dd H:mm:ss", x)}

 

${timer("yyyy-MM-dd ", x)} 

 
 
在模板中除了可以通過對象來調用方法外(${object.methed(args)})也可以直接調用java實現的方法,java類必須實現接口TemplateMethodModel的方法exec(List args). 下面以把毫秒的時間轉換成按格式輸出的時間爲例子

public class LongToDate implements TemplateMethodModel {

      public TemplateModel exec(List args) throws TemplateModelException { SimpleDateFormat mydate = new SimpleDateFormat((String) args.get(0)));         return mydate.format(new Date(Long.parseLong((String)args.get(1)));     }

將LongToDate對象放入到數據模型中 root.put("timer", new IndexOfMethod()); ftl模板裏使用 <#assign x = "123112455445"> ${timer("yyyy-MM-dd H:mm:ss", x)} ${timer("yyyy-MM-dd ", x)} 

 

 
輸出
2001-10-12 5:21:12
2001-10-12
 
自定義 Transforms
實現自定義的<@transform>文本或表達式</@transform>的功能,允許對中間的最終文本進行解析轉換
 
例子:實現<@upcase>str</@upcase> 將str轉換成STR 的功能
 
代碼如下:

import java.io.*;

  import java.util.*; import freemarker.template.TemplateTransformModel;   class UpperCaseTransform implements TemplateTransformModel {       public Writer getWriter(Writer out, Map args) {         return new UpperCaseWriter(out);     }       private class UpperCaseWriter extends Writer {                private Writer out;                    UpperCaseWriter (Writer out) {             this.out = out;         }           public void write(char[] cbuf, int off, int len)                 throws IOException {             out.write(new String(cbuf, off, len).toUpperCase());         }           public void flush() throws IOException {             out.flush();         }           public void close() {         }     }

然後將此對象put到數據模型中

 
root.put("upcase", new UpperCaseTransform());
 
在view(ftl)頁面中可以如下方式使用
 
<@upcase>
hello world
</@upcase>
 
打印輸出:
HELLO WORLD
 
 
 
 
FBuilt-ins
${x?upper_case} – 小寫變大寫
${test?html} - 轉換爲HTML編碼格式
${repeat("A", B)} – 複製B次A
 
Example:
${test?html}
${test?upper_case?html}
Assuming that test stores the string ``Tom & Jerry'', the output will be:
Tom &amp; Jerry
TOM &amp; JERRY
 
---------
${repeat("What", 3)}
will print: WhatWhatWhat 
 
1. String內置的JavaScript轉換: js_string
用途:用於JavaScript轉義,轉換',",換行等特殊字符
模板:
<script>
alert("${errorMessage?js_string}");
</script>
輸出:
<script>
alert("Readonly\'s pet name is \"Cross Bone\"");
</script>
2.內置的默認值處理:default
用途: 用於處理默認值
模本:
User: ${userLogin.name?default("Anonymous")}
<td>${(employee.department.manager.name)?default("&nbsp;")}</td>
輸出:
User: Anonymous
<td>&nbsp;</td>
注,可以對整個對象樹加上(),再用內置處理器這種方便的做法,偶也是最近剛學會的,以前一直用很傻的方法做.....
3. Sequence內置的計數器: xxx_index
用途:顯示序號
模板:
<#list employees as e>
${e_index}. ${e.name}
</#list>
輸出:
1. Readonly
2. Robbin
4. Sequence內置的分段器: chunk
用途:某些比較BT的排版需求
模板:
<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']>
<#list seq?chunk(4) as row>
<ul>
<li><#list row as cell>${cell} </#list>

</#list>
<#list seq?chunk(4, '-') as row>
<tr>
<td><#list row as cell>${cell} </#list></td>
</tr>
</#list>
輸出:
<ul>
<li>a
<li>b
<li>c
<li>d

<ul>
<li>e
<li>f
<li>g
<li>h

<ul>
<li>i
<li>j
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
<tr>
<td>e</td>
<td>f</td>
<td>g</td>
<td>h</td>
</tr>
<tr>
<td>i</td>
<td>j</td>
<td>-</td>
<td>-</td>
</tr>
String
${"It's \"quoted\" and
this is a backslash: \\"}


${'It\'s "quoted" and
this is a backslash: \\'}


${r"${foo}"}
raw
字符串,原封不動地現實引號中的內容


ps:前一種是用雙引號來引用字符串,後一種是用單引號來引用字符串。
分別需要對雙引號和單引號進行轉義


${"${user}${user}${user}${user}"}
${user + user + user + user}

效果相同


★substring
${user[0]}${user[4]}
${user[1..4]}
${user[4..]}



★number
不支持科學計數法
小數點前面的零不能省略


★sequences
<#list ["winter", "spring", "summer", "autumn"] as x>
${x}
</#list>


<#list 2..5 as x> ${x} </#list>
<#list [2,3,4,5] as x> ${x} </#list>



數組的拼接
<#list ["Joe", "Fred"] + ["Julia", "Kate"] as user>
- ${user}
</#list>



★hash
<#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}>
- Joe is ${ages.Joe}
- Fred is ${ages.Fred}
- Julia is ${ages.Julia}

注意重複的鍵對應的值取最後的一個


★運算
${5/2?int} 顯示2
 
cap_first : 首字母大寫
 
capitalize: 所有單詞首刺目大寫
 
html : 轉換爲HTML格式
  • < replaced with &lt;
  • > replaced with &gt;
  • & replaced with &amp;
  • " replaced with &quot;
index_of : 顯示元素所在的位置
"abcabc"?index_of("bc")
返回值爲1(下標從0開始)
 
Contains:判斷是否存在字符
<#if "piceous"?contains("ice")>It contains "ice"</#if>
輸出: It contains "ice"
 
Replace :替換
 
split(“XX”):截取XX之後的字符
 
<#list "someMOOtestMOOtext"?split("MOO") as x>
- ${x}
</#list>
 
輸出:
- some
- test
- text
 
 
starts_with :字符串由什麼開始返回布爾型
 
trim :去掉空格
 
seq_index_of 數組中元素的位置
 
<#assign colors = ["red", "green", "blue"]>
${colors?seq_index_of("blue")}

輸出: 2

    Default : 設置變量的默認值

 

 
Exists:放在if句 如果沒有…..
 
<#if mouse?exists>
 Mouse found
<#else>
 No mouse found
</#if>
Creating mouse...
<#assign mouse = "Jerry">
<#if mouse?exists>
 Mouse found
<#else>
 No mouse found
</#if> 

輸出 :

  No mouse found

Creating mouse...

 
 Mouse found 
 
if_exists 放在一般語句
 
(${mouse?if_exists})
Creating mouse...
<#assign mouse = "Jerry">
(${mouse?if_exists}) 
輸出:
()
Creating mouse...
(Jerry) 
 
 
刪除空白行和空格
<#compress>
 ...
</#compress>
 
讓此標記內的代碼都執行<#escape 後的?參數
 
<#escape>
 
</#escape>
 
<#escape x as x?html>
 From: ${mailMessage.From}
 Subject: ${mailMessage.Subject}
 <#noescape>Message: ${mailMessage.htmlFormattedBody}</#noescape>
 ...
</#escape>
 
輸出:
From: ${mailMessage.From?html}
 Subject: ${mailMessage.Subject?html}
 Message: ${mailMessage.htmlFormattedBody}
  ...
 
 
 
 
 
 [A1]默認值
 [A2]<#import “lib/abc.ftl” as abc>這裏的abc叫做namespace

 

 

<hr> Copyright 2001-2002 Juila Smith All rights reserved.    <hr>  <ul>       <li>Mouse       <li>Elephant       <li>Python
發佈了69 篇原創文章 · 獲贊 7 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章