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