| 3、模板 (1)整體結構 l???????? 模板使用FTL(FreeMarker模板語言)編寫,是下面各部分的一個組合: ????????? 文本:直接輸出 ????????? Interpolation:由${和},或#{和}來限定,計算值替代輸出 ????????? FTL標記:FreeMarker指令,和HTML標記類似,名字前加#予以區分,不會輸出 ????????? 注釋:由<#--和-->限定,不會輸出 l???????? 下面是以一個具體模板例子: <html>[BR] <head>[BR] ??<title>Welcome!</title>[BR] </head>[BR] <body>[BR] ??<#--?Greet?the?user?with?his/her?name?-->[BR] ??<h1>Welcome?${user}!</h1>[BR] ??<p>We?have?these?animals:[BR] ??<ul>[BR] ??<#list?animals?as?being>[BR] ????<li>${being.name}?for?${being.price} Euros[BR] ??</#list>[BR] ??</ul>[BR] </body>[BR] </html>? l???????? [BR]是用于換行的特殊字符序列 l???????? 注意事項: ????????? FTL區分大小寫,所以list是正確的FTL指令,而List不是;${name}和${NAME}是不同的 ????????? Interpolation只能在文本中使用 ????????? FTL標記不能位于另一個FTL標記內部,例如: <#if <#include 'foo'>='bar'>...</if> ????????? 注釋可以位于FTL標記和Interpolation內部,如下面的例子: <h1>Welcome?${user <#-- The name of user -->}!</h1>[BR] <p>We?have?these?animals:[BR] <ul>[BR] <#list?<#-- some comment... --> animals as?<#-- again... --> being>[BR] ...? ????????? 多余的空白字符會在模板輸出時移除 (2)指令 l???????? 在FreeMarker中,使用FTL標記引用指令 l???????? 有三種FTL標記,這和HTML標記是類似的: ????????? 開始標記:<#directivename parameters> ????????? 結束標記:</#directivename> ????????? 空內容指令標記:<#directivename parameters/> l???????? 有兩種類型的指令:預定義指令和用戶定義指令 l???????? 用戶定義指令要使用@替換#,如<@mydirective>...</@mydirective>(會在后面講述) l???????? FTL標記不能夠交叉,而應該正確的嵌套,如下面的代碼是錯誤的: <ul> <#list animals as being> ? <li>${being.name} for ${being.price} Euros ? <#if use = "Big Joe"> ???? (except for you) </#list> </#if><#-- WRONG! --> </ul>? l???????? 如果使用不存在的指令,FreeMarker不會使用模板輸出,而是產生一個錯誤消息 l???????? FreeMarker會忽略FTL標記中的空白字符,如下面的例子: <#list[BR] ??animals???????as[BR] ?????being[BR] >[BR] ${being.name}?for?${being.price}?Euros[BR] </#list????>? l???????? 但是,<、</和指令之間不允許有空白字符 (3)表達式 l???????? 直接指定值 ????????? 字符串 n???????? 使用單引號或雙引號限定 n???????? 如果包含特殊字符需要轉義,如下面的例子: ${"It's \"quoted\" and this is a backslash: \\"} ? ${'It\'s "quoted" and this is a backslash: \\'}? 輸出結果是: It's "quoted" and this is a backslash: \ ? It's "quoted" and this is a backslash: \? n???????? 下面是支持的轉義序列: | 轉義序列 | 含義 | | \" | 雙引號(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代碼 | n???????? 有一類特殊的字符串稱為raw字符串,被認為是純文本,其中的\和{等不具有特殊含義,該類字符串在引號前面加r,下面是一個例子: ${r"${foo}"} ${r"C:\foo\bar"}? 輸出的結果是: ${foo} C:\foo\bar? ????????? 數字 n???????? 直接輸入,不需要引號 n???????? 精度數字使用“.”分隔,不能使用分組符號 n???????? 目前版本不支持科學計數法,所以“1E3”是錯誤的 n???????? 不能省略小數點前面的0,所以“.5”是錯誤的 n???????? 數字8、+8、08和8.00都是相同的 ????????? 布爾值 n???????? true和false,不使用引號 ????????? 序列 n???????? 由逗號分隔的子變量列表,由方括號限定,下面是一個例子: <#list ["winter", "spring", "summer", "autumn"] as x> ${x} </#list>? 輸出的結果是: winter spring summer autumn n???????? 列表的項目是表達式,所以可以有下面的例子: [2 + 2, [1, 2, 3, 4], "whatnot"] n???????? 可以使用數字范圍定義數字序列,例如2..5等同于[2, 3, 4, 5],但是更有效率,注意數字范圍沒有方括號 n???????? 可以定義反遞增的數字范圍,如5..2 ????????? 散列(hash) n???????? 由逗號分隔的鍵/值列表,由大括號限定,鍵和值之間用冒號分隔,下面是一個例子: {"name":"green?mouse", "price":150} n???????? 鍵和值都是表達式,但是鍵必須是字符串 l???????? 獲取變量 ????????? 頂層變量: ${variable},變量名只能是字母、數字、下劃線、$、@和#的組合,且不能以數字開頭 ????????? 從散列中獲取數據 n???????? 可以使用點語法或方括號語法,假設有下面的數據模型: (root) | +- book |?? | |?? +- title = "Breeding green mouses" |?? | |?? +- author |?????? | |?????? +- name = "Julia Smith" |?????? | |?????? +- info = "Biologist, 1923-1985, Canada" | +- test = "title"? 下面都是等價的: book.author.name book["author"].name book.author.["name"] book["author"]["name"] n???????? 使用點語法,變量名字有頂層變量一樣的限制,但方括號語法沒有該限制,因為名字是任意表達式的結果 ????????? 從序列獲得數據:和散列的方括號語法語法一樣,只是方括號中的表達式值必須是數字;注意:第一個項目的索引是0 ????????? 序列片斷:使用[startIndex..endIndex]語法,從序列中獲得序列片斷(也是序列);startIndex和endIndex是結果為數字的表達式 ????????? 特殊變量:FreeMarker內定義變量,使用.variablename語法訪問 l???????? 字符串操作 ????????? Interpolation(或連接操作) n???????? 可以使用${..}(或#{..})在文本部分插入表達式的值,例如: ${"Hello ${user}!"} ${"${user}${user}${user}${user}"}? n???????? 可以使用+操作符獲得同樣的結果 ${"Hello " + user + "!"} ${user + user + user + user} n???????? ${..}只能用于文本部分,下面的代碼是錯誤的: <#if ${isBig}>Wow!</#if> <#if "${isBig}">Wow!</#if> 應該寫成: <#if isBig>Wow!</#if> ????????? 子串 n???????? 例子(假設user的值為“Big Joe”): ${user[0]}${user[4]} ${user[1..4]} 結果是(注意第一個字符的索引是0): BJ ig J? l???????? 序列操作 ????????? 連接操作:和字符串一樣,使用+,下面是一個例子: <#list ["Joe", "Fred"] + ["Julia", "Kate"] as user> - ${user} </#list> 輸出結果是: - Joe - Fred - Julia - Kate l???????? 散列操作 ????????? 連接操作:和字符串一樣,使用+,如果具有相同的key,右邊的值替代左邊的值,例如: <#assign ages = {"Joe":23, "Fred":25} + {"Joe":30, "Julia":18}> - Joe is ${ages.Joe} - Fred is ${ages.Fred} - Julia is ${ages.Julia}? 輸出結果是: - Joe is 30 - Fred is 25 - Julia is 18? l???????? 算術運算 ????????? +、-、×、/、%,下面是一個例子: ${x * x - 100} ${x / 2} ${12 % 10} 輸出結果是(假設x為5): -75 2.5 2? ????????? 操作符兩邊必須是數字,因此下面的代碼是錯誤的: ${3 * "5"} <#-- WRONG! -->? ????????? 使用+操作符時,如果一邊是數字,一邊是字符串,就會自動將數字轉換為字符串,例如: ${3 + "5"}? 輸出結果是: 35 ????????? 使用內建的int(后面講述)獲得整數部分,例如: ${(x/2)?int} ${1.1?int} ${1.999?int} ${-1.1?int} ${-1.999?int} 輸出結果是(假設x為5): 2 1 1 -1 -1 l???????? 比較操作符 ????????? 使用=(或==,完全相等)測試兩個值是否相等,使用!= 測試兩個值是否不相等 ????????? =和!=兩邊必須是相同類型的值,否則會產生錯誤,例如<#if 1 = "1">會引起錯誤 ????????? Freemarker是精確比較,所以對"x"、"x? "和"X"是不相等的 ????????? 對數字和日期可以使用<、<=、>和>=,但不能用于字符串 ????????? 由于Freemarker會將>解釋成FTL標記的結束字符,所以對于>和>=可以使用括號來避免這種情況,例如<#if (x > y)> ????????? 另一種替代的方法是,使用lt、lte、gt和gte來替代<、<=、>和>= l???????? 邏輯操作符 ????????? &&(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>? l???????? 內建函數 ????????? 內建函數的用法類似訪問散列的子變量,只是使用“?”替代“.”,下面列出常用的一些函數 ????????? 字符串使用的: n???????? html:對字符串進行HTML編碼 n???????? cap_first:使字符串第一個字母大寫 n???????? lower_case:將字符串轉換成小寫 n???????? upper_case:將字符串轉換成大寫 n???????? trim:去掉字符串前后的空白字符 ????????? 序列使用的: n???????? size:獲得序列中元素的數目 ????????? 數字使用的: n???????? int:取得數字的整數部分(如-1.9?int的結果是-1) ????????? 例子(假設test保存字符串"Tom & Jerry"): ${test?html} ${test?upper_case?html} 輸出結果是: Tom & Jerry TOM & JERRY? l???????? 操作符優先順序 | 操作符組 | 操作符 | | 后綴 | [subvarName] [subStringRange] . (methodParams) | | 一元 | +expr、-expr、! | | 內建 | ? | | 乘法 | *、 / 、% | | 加法 | +、- | | 關系 | <、>、<=、>=(lt、lte、gt、gte) | | 相等 | ==(=)、!= | | 邏輯and | && | | 邏輯or | || | | 數字范圍 | .. | (4)Interpolation l???????? Interpolation有兩種類型: ????????? 通用Interpolation:${expr} ????????? 數字Interpolation:#{expr}或#{expr; format} l???????? 注意:Interpolation只能用于文本部分 l???????? 通用Interpolation ????????? 插入字符串值:直接輸出表達式結果 ????????? 插入數字值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個例子: <#setting number_format="currency"/> <#assign answer=42/> ${answer} ${answer?string}? <#-- the same as ${answer} --> ${answer?string.number} ${answer?string.currency} ${answer?string.percent}? 輸出結果是: $42.00 $42.00 42 $42.00 4,200% ????????? 插入日期值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個使用格式模式的例子: ${lastUpdated?string("yyyy-MM-dd HH:mm:ss zzzz")} ${lastUpdated?string("EEE, MMM d, ''yy")} ${lastUpdated?string("EEEE, MMMM dd, yyyy, hh:mm:ss a '('zzz')'")}? 輸出的結果類似下面的格式: 2003-04-08 21:24:44 Pacific Daylight Time Tue, Apr 8, '03 Tuesday, April 08, 2003, 09:24:44 PM (PDT) ????????? 插入布爾值:根據缺省格式(由#setting指令設置)將表達式結果轉換成文本輸出;可以使用內建函數string格式化單個Interpolation,下面是一個例子: <#assign foo=true/> ${foo?string("yes", "no")} 輸出結果是: yes l???????? 數字Interpolation的#{expr; format}形式可以用來格式化數字,format可以是: ????????? mX:小數部分最小X位 ????????? MX:小數部分最大X位 ????????? 例子: ?????????? <#-- If the language is US English the output is: --> <#assign x=2.582/> <#assign y=4/> #{x; M2}?? <#-- 2.58 --> #{y; M2}?? <#-- 4??? --> #{x; m1}?? <#-- 2.6 --> #{y; m1}?? <#-- 4.0 --> #{x; m1M2} <#-- 2.58 --> #{y; m1M2} <#-- 4.0? -->? |