20200427 FTL 模板語言參考 梳理 (常用)

官方鏈接:http://freemarker.foofun.cn/ref_deprecated.html

1.內建函數參考

1.1 字母順序索引(重要)

在 FreeMarker 2.3.23 中,指令名可以使用駝峯樣式來代替蛇形樣式, 比如 startsWith 代替 starts_with。 但是要知道,在相同模版內,FreeMarker 會強制對模板語言部分的所有標識符使用駝峯樣式 (用戶自定義名稱不會受影響)。

 

 

該內建函數和 xml 內建函數的唯一不同是 xhtml內建函數轉義 ' 爲 ',而不是 ', 因爲一些老版本的瀏覽器不能正確解釋 '

 

  • abs

  • 給出數字的絕對值。比如 x?abs ,如果 x 是 -5,會得到5。

  • ancestors

  • 一個包含所有結點祖先結點的序列,以直接父結點開始,以根結點結束。 該內建函數的結果也是一個方法,你可以用它和元素的 完全限定名 來過濾結果。 比如以名稱 section 用 node?ancestors("section") 來獲得所有祖先結點的序列。

  • api

  • 如果value本身支持這個額外的特性, value?api 提供訪問 value 的API (通常是 Java API),比如 value?api.someJavaMethod(), 當需要調用對象的Java方法時,這種方式很少使用, 但是 FreeMarker 揭示的value的簡化視圖的模板隱藏了它,也沒有相等的內建函數。 例如,當有一個 Map,並放入數據模型 (使用默認的對象包裝器),模板中的 myMap.myMethod() 基本上翻譯成Java的 ((Method) myMap.get("myMethod")).invoke(...),因此不能調用 myMethod。如果編寫了 myMap?api.myMethod() 來代替,那麼就是Java中的 myMap.myMethod()

  • boolean

  • 字符串轉爲布爾值。字符串必須是 true 或 false (大小寫敏感!),或者必須是由 boolean_format 設置的特定格式。

  • byte

  • 返回一個包含原變量中相同值的 SimpleNumber, 但是在內部表示值中使用了 java.lang.Type。 如果方法被重載了,這是有用的,或者一個 TemplateModel 解包器在自動選擇適合的 java.lang.* 類型有問題時。 請注意,從2.3.9版本開始,解包器有本質上改進, 所以將基本不會使用到這些內建函數來轉換數字類型了, 除非在重載方法調用中來解決一些含糊的東西。

  • 內建函數 long 也可以用於日期, 時間和時間日期類型的值來獲取返回爲 java.util.Date.getTime() 的值。如果你不得不調用使用 long 類型時間戳的Java方法時, 這是非常有用的。這個轉換不是自動進行的。

  • for stringsfor booleans

  • 該內建函數將布爾值轉換爲字符串,針對 "計算機語言" 而不是用戶。不管 boolean_format 的設置是什麼, 結果是 "true" 或 "false"。 當生成JavaScript的時候,應該會用到它,否則修改 boolean_format 的話可以打斷生成的計算機語言輸出。

  • foo?string("yes", "no"): 從 FreeMarker 2.3.23 版本開始廢棄:使用 ?then("yes", "no") 來替代。如果布爾值是true, 這會返回第一個參數(此處是:"yes"), 否則返回第二個參數(此處是:"no")。 請注意,返回值總是一個字符串;如果參數是數字,那麼首先會轉換成字符串。 也請注意,兩個參數是評估過的,不管只有一個會被用到; 如果參數不僅僅是文字的話,這也許會有負面影響。

  • foo?string: 從 FreeMarker 2.3.20 版本開始廢棄:使用 ?c 來代替,或者設置 boolean_format 設置項,比如像 "yes,no",之後轉換會自動發生。 如果仍然需要知道,這會轉換布爾值爲字符串,使用默認字符串來顯示 true 和 false 值。默認情況下,true 被呈現爲 "true", 而 false 被呈現爲 "false"。 如果使用 FreeMarker 來生成代碼,這是很有用的 (但是從 2.3.20 版本開始, 請使用 ?c),因爲這些值不是非本地化(語言,國家)敏感的。 要修改這些默認設置,可以使用 boolean_format 設置

  • cap_first

  • 字符串中的首單詞的首字母大寫。 關於"單詞"的準確意義,可以參考 word_list 內建函數。 例如:

  • capitalize

  • 字符串中所有單詞的首字母大寫。 關於"單詞"的準確意義,可以參考 word_list 內建函數。例如:

  • ceiling

  • ceiling:返回數字小數進位後的整數 (也就是向正無窮進位)

  • children

  • 一個包含該結點所有子結點(也就是直接後繼結點)的序列。

  • XML:這和特殊的哈希表的鍵 * 幾乎是一樣的。 除了它返回所有結點,而不但是元素。所以可能的子結點是元素結點, 文本結點,註釋結點,處理指令結點等,但 不是 屬性結點。屬性結點排除在序列之外。

  • chop_linebreak

  • 在末尾沒有 換行符 的字符串, 那麼可以換行,否則不改變字符串。

  • chunk

  • 該內建函數將序列分隔爲多個序列,長度爲第一個參數給定的值 (比如 mySeq?chunk(3))。結果是包含這些序列的一個序列。 最後一個序列可能比給定的長度要小,除非第二個參數也給定了 (比如 比如 mySeq?chunk(3, '-')), 這就是用來填充最後一個序列,以達到給定的長度。例如:

  • contains

  • 如果函數中的參數指定的子串出現在源字符串中, 那麼返回true。比如:

  • counter

  • 返回當前迭代(由循環變量名稱識別)從1開始的索引。

  • date for datesfor strings

  • 這些內建函數用來指定日期變量中的哪些部分被使用:

  • date:僅日期部分,沒有一天當中的時間部分。

  • time:僅一天當中的時間部分,沒有日期部分。

  • datetime:日期和時間都在

  • 在最佳情況下,你不需要使用這些內建函數。不幸的是, 由於Java平臺上的技術限制,FreeMarker 有時不能發現日期中的哪一部分在使用; 詢問程序員哪些變量會有這個問題。如果 FreeMarker 不得不執行需要這些信息的操作 --比如用文本顯示日期--但是它不知道哪一部分在使用,它會以錯誤來中止運行。 這就是你不得不使用這些內建函數的時候了。比如,假設 openingTime 是一個有這樣問題的變量:

  • date_if_unknown

  • date_if_unknown, time_if_unknown, datetime_if_unknown 內建函數使用一些子類型來標記日期類型的值:日期沒有時間,時間,或日期-時間。 如果變量值已經持有這些信息,那麼內建函數就不會起作用。也就是說, 它不會轉換變量值的子類型,如果它是未知的,則會添加子類型。

  • datetime for datesfor strings

  • datetime_if_unknown

  • date_if_unknown, time_if_unknown, datetime_if_unknown 內建函數使用一些子類型來標記日期類型的值:日期沒有時間,時間,或日期-時間。 如果變量值已經持有這些信息,那麼內建函數就不會起作用。也就是說, 它不會轉換變量值的子類型,如果它是未知的,則會添加子類型。

  • double

  • 返回一個包含原變量中相同值的 SimpleNumber, 但是在內部表示值中使用了 java.lang.Type。 如果方法被重載了,這是有用的,或者一個 TemplateModel 解包器在自動選擇適合的 java.lang.* 類型有問題時。 請注意,從2.3.9版本開始,解包器有本質上改進, 所以將基本不會使用到這些內建函數來轉換數字類型了, 除非在重載方法調用中來解決一些含糊的東西。

  • 內建函數 long 也可以用於日期, 時間和時間日期類型的值來獲取返回爲 java.util.Date.getTime() 的值。如果你不得不調用使用 long 類型時間戳的Java方法時, 這是非常有用的。這個轉換不是自動進行的。

  • ends_with

  • 返回是否這個字符串以參數中指定的子串結尾。 比如 "ahead"?ends_with("head") 返回布爾值 true"head"?ends_with("head") 也返回 true

  • ensure_ends_with

  • 如果字符串沒有以第一個參數指定的子串結尾, 那麼就會將它加到字符串後面,否則返回原字符串。比如, "foo"?ensure_ends_with("/") 和 "foo/"?ensure_ends_with("/") 返回 "foo/"

  • ensure_starts_with

  • 如果字符串沒有以第一個參數指定的子串開頭, 那麼就會將它加到字符串開頭,否則返回原字符串。比如, "foo"?ensure_starts_with("/") 和 "/foo"?ensure_starts_with("/") 返回 "/foo"

  • 如果指定兩個參數,那麼第一個參數就被解釋成Java正則表達式, 如果它不匹配字符串的開頭,那麼第二個參數指定的字符串就會添加到字符串開頭。 比如 someURL?ensure_starts_with("[a-zA-Z]+://", "http://") 就會檢查如果字符串是否以 "[a-zA-Z]+://" 開頭 (請注意,不需要 ^),如果不是的話,就添加 "http://"

  • 該方法也接受第三個標誌位參數。因爲調用兩個參數暗指 "r"(也就是正則表達式模式),那麼就需要第三個參數了。 值得注意的一點是當不需要第一參數被解釋成正則表達式,而只是普通文本, 但是又想讓比較是大小寫敏感的,那麼此時就需要使用 "i" 作爲第三個參數。

  • eval

  • 這個函數求一個作爲FTL表達式的字符串的值。比如 "1+2"?eval返回數字3。

  • 在調用 eval 的地方, 已被求值的表達式看到相同的變量(比如本地變量)是可見的。 也就是說,它的行爲就像在 s?eval 處, 你有 s 的 。除了,指向在 s 之外創建的循環變量,它不能使用 循環變量內建函數

  • 配置設置項影響來自 Configuration 對象表達式解析(比如語法),而不是來自調用 eval 的的模板。

  • first

  • 序列的第一個子變量。如果序列爲空,那麼模板處理將會中止。

  • floor

  • floor:返回數字的舍掉小數後的整數 (也就是向負無窮捨棄)

  • groups

  • 這個函數只作用於內建函數 matches 的結果。請參考 這裏...

  • float

  • has_api

  • has_content

  • 如果變量(不是Java的 null) 存在而且不是"空"就返回 true,否則返回 false。"空”"含義靠具體的情形來決定。 它是直觀的常識性概念。下面這些都是空:長度爲0的字符串, 沒有子變量的序列或哈希表,一個已經超過最後一項元素的集合。 如果值不是字符串,序列,哈希表或集合,如果它是數字,日期或布爾值 (比如 0 和 false 是非空的), 那麼它被認爲是非空的,否則就是空的。注意當你的數據模型實現了多個模板模型接口, 你可能會得到不是預期的結果。然而,當你有疑問時你通常可以使用 expr!?size > 0 或 expr!?length > 0 來代替 expr?has_content

  • has_next

  • 辨別循環項是否是當前迭代(由循環變量名稱識別)的最後一項。

  • html

  • index

  • index_of

  • 返回第一次字符串中出現子串時的索引位置。 例如 "abcabc"?index_of("bc") 將會返回1 (不要忘了第一個字符的索引是0)。而且,你可以指定開始搜索的索引位置: "abcabc"?index_of("bc", 2) 將會返回4。 這對第二個參數的數值沒有限制:如果它是負數,那就和是0是相同效果了, 如果它比字符串的長度還大,那麼就和它是字符串長度那個數值是一個效果。 小數會被切成整數。

  • 如果第一個參數作爲子串沒有在該字符串中出現時 (如果你使用了第二個參數,那麼就從給定的序列開始),那麼就返回-1。

  • int

  • interpret

  • item_cycle

  • item_parity

  • item_parity_cap

  • is_even_item

  • is_first

  • 序列的第一個子變量。如果序列爲空,那麼模板處理將會中止。

  • is_infinite

  • 辨別數字是否是無限浮點數(根據IEEE 754)。比如, 基於 someNumber 的值是否是無限, someNumber?is_infinite 結果是 true 或 false,當然, 如果該數不是浮點類型,那麼將會返回 false

  • is_last

  • is_nan

  • 辨別數字是否是浮點數NaN(根據IEEE 754)。比如, 基於 someNumber 的值是否是 NaN, someNumber?is_nan 結果是 true 或 false,當然, 如果該數不是浮點類型,那麼將會返回 false

  • is_odd_item

  • is_type

  • 內建函數 如果值是 … 時返回 true
    is_string 字符串
    is_number 數字
    is_boolean 布爾值
    is_date 不要使用它!使用 is_date_like 來代替, 它們是相同的。往後也許會修改它的含義爲 date_only
    is_date_like 日期,也就似乎日期,時間或者日期-時間, 亦或者是未知精確類型的日期(從 FreeMarker 2.3.21 版本開始)
    is_date_only 日期 (沒有時間部分) (從 FreeMarker 2.3.21 版本開始)
    is_time 時間 (沒有年-月-日部分) (從 FreeMarker 2.3.21 版本開始)
    is_datetime 日期-時間 (包含年-月-日和時間兩者)
    is_unknown_date_like 不清楚是日期或時間或日期-時間的日期
    is_method 方法
    is_transform 變換
    is_macro 宏或函數(當然,由於歷史問題,也對函數有效)
    is_hash 哈希表 (包含擴展的哈希表)
    is_hash_ex 擴展的哈希表 (支持 ?keys 和 ?values)
    is_sequence 序列
    is_collection 集合 (包含擴展的集合)
    is_collection_ex 擴展的集合 (支持 ?size)
    is_enumerable 序列或集合
    is_indexable 序列
    is_directive 指令類型 (例如宏 或 TemplateDirectiveModel, TemplateTransformModel, 等...), 或者函數 (由於歷史問題)
    is_node 結點
  • iso, iso_...

  • 這些內建函數轉換日期,時間或日期-時間值爲字符串,遵循 ISO 8601:2004 "擴展" 格式。

  • 該內建函數有很多表現形式: iso_utc, iso_local, iso_utc_nz, iso_local_nz, iso_utc_m, iso_utc_m_nz,等。 名稱的構成由下列單詞順序組成,每部分由一個 _ 分隔開:

    • iso (必須的)

  • j_string

  • 根據Java語言字符串轉義規則來轉義字符串, 所以它很安全的將值插入到字符串類型中。要注意它 不會 在被插入的值的兩側添加引號; 你需要在字符串值 內部 來使用。

  • join

  • 使用給定的分隔符來連接序列中的項爲一個獨立的字符串,例如:

  • js_string

  • keep_after

  • 移除字符串中的一部分內容,該部分是給定子串第一次出現之前的部分。 比如:

  • keep_after_last

  • keep_before

  • keep_before_last

  • keys

  • 一個包含哈希表中查找到的鍵的序列。 請注意,並不是所有的哈希表都支持這個 (詢問程序員一個指定的哈希表是否允許這麼操作)。

  • last

  • 序列的最後一個子變量。如果序列爲空,那麼模板處理將會中止。

  • last_index_of

  • left_pad

  • length

  • 字符串中字符的數量。

  • long

  • 內建函數 long 也可以用於日期, 時間和時間日期類型的值來獲取返回爲 java.util.Date.getTime() 的值。如果你不得不調用使用 long 類型時間戳的Java方法時, 這是非常有用的。這個轉換不是自動進行的。

  • lower_abc

  • 將 1, 2, 3,等...,轉換爲字符串 "a", "b", "c",等... 當到達 "z"時,那麼會繼續轉換成如 "aa", "ab",等... 這和電子表格應用程序(比如Excel或Calc) 的列標籤有着相同的邏輯。數字的最小值是 1。 沒有上限值。如果數字是 0 或更小或它不是整數, 那麼模板處理將會中止併發生錯誤。

  • lower_case

  • 字符串的小寫形式。比如 "GrEeN MoUsE"?lower_case 將會是 "green mouse"

  • matches

  • 該內建函數決定了字符串是否精確匹配模式。而且,它會返回匹配子串的列表。 返回值是多類型值:

  • 布爾值:如果字符串整體匹配了模式,就是 true, 否則就是 false。比如:"fooo"?matches('fo*') 就是 true,但是 "fooo bar"?matches('fo*') 是 false

  • 序列:字符串匹配的子串的列表。很有可能是長度爲0的序列。

  • namespace

  • 該內建函數返回和宏變量或函數變量關聯的命名空間 (也就是命名空間的"入口"哈希表)。你只能和宏和函數一起來用它。

  • new

  • 這是用來創建一個確定的 TemplateModel 實現變量的內建函數。

  • 在 ? 的左邊你可以指定一個字符串, 是 TemplateModel 實現類的完全限定名。 結果是調用構造方法生成一個方法變量,然後將新變量返回。

  • node_namespace

  • 返回結點命名空間的字符串。FreeMarker 沒有爲結點命名空間定義準確的含義; 它依賴於變量是怎麼建模的。也可能結點沒有定義任何結點命名空間。 這種情形下,該函數應該返回未定義的變量 (也就是 node?node_namespace?? 的值是 false),所以不能使用這個返回值。

  • XML:這種情況下的XML,就是XML命名空間的URI (比如 "http://www.w3.org/1999/xhtml")。 如果一個元素或屬性結點沒有使用XML命名空間,那麼這個函數就返回一個空字符串。 對於其他XML結點這個函數返回未定義的變量。

  • node_name

  • 當被"訪問"時,返回用來決定哪個自定義指令來調用控制這個結點的字符串。 可以參見 visit 和 recurse 指令。

  • XML:如果結點是元素或屬性,那麼字符串就會是元素或屬性的本地 (沒有前綴)名字。否則,名稱通常在結點類型之後以 @ 開始。 可以參見 該表格。 要注意這個結點名稱與在DOM API中返回的結點名稱不同; FreeMarker 結點名稱的目標是給要處理結點的用戶自定義指令命名。

  • node_type

  • 描述結點類型的字符串。FreeMarker 沒有對結點類型定義準確的含義; 它依賴於變量是怎麼建模的。也可能結點並不支持結點類型。 在這種情形下,該函數就返回未定義值,所以就不能使用返回值。 (可以用 node?node_type?? 繼續檢查一個結點是否是支持類型屬性。)

  • XML:可能的值是: "attribute", "text", "comment", "document_fragment", "document", "document_type", "element", "entity", "entity_reference", "notation", "pi"。 請注意,沒有 "cdata" 類型,因爲CDATA被認爲是普通文本元素。

  • number

  • 字符串轉化爲數字格式。這個數字必須是 "計算機語言" 格式。也就是說, 它必須是本地化獨立的形式,小數的分隔符就是一個點,沒有分組。

  • 該內建函數識別FreeMarker模板語言使用的數字格式。此外, 它也識別科學記數法(比如 "1.23E6""1.5e-8") 從 FreeMarker 2.3.21 版本開始,它也識別所有XML Schema數字格式,比如 NaNINF-INF, 還有Java本地格式Infinity 和 -Infinity

  • 如果字符串不是適當的格式,當嘗試訪問該內建函數時就會發生錯誤, 並中止模板執行。

  • number_to_date, number_to_datetime, number_to_time

  • parent

  • 在結點樹中,返回該結點的直接父結點。根結點沒有父結點, 所以對於根結點,表達式 node?parent?? 的值就是 false

  • XML:注意通過這個函數返回的值也是一個序列 (當編寫 someNode[".."] 時,和XPath表達式 .. 的結果是一樣的)。也要注意屬性結點, 它返回屬性所屬的元素結點,儘管屬性結點不被算作是元素的子結點。

  • replace

  • 在源字符串中,用另外一個字符串來替換原字符串中出現它的部分。 它不處理詞的邊界。比如:

  • remove_beginning

  • 從字符串的開頭移除參數中的子串,如果它不以參數中的子串開頭, 那麼就或者返回原字符串。比如:

  • remove_ending

  • reverse

  • 序列的反序形式。

  • right_pad

  • 它和 left_pad 相同, 但是它從末尾開始插入字符而不是從開頭。

  • round

  • 使用確定的舍入法則,轉換一個數字到整數:

  • root

  • 該結點所屬結點樹的根結點。

  • XML:根據W3C,XML文檔的根結點不是最頂層的元素結點, 而是文檔本身,是最高元素的父結點。例如, 如果想得到被稱爲是 foo 的XML (所謂的"文檔元素",不要和"文檔"搞混了)的最高 元素, 那麼不得不編寫 someNode?root.foo。如果僅僅寫了 someNode?root,那麼得到的是文檔本身,而不是文檔元素。

  • rtf

  • 字符串作爲富文本(RTF 文本),也就是說,下列字符串:

  • \ 替換爲 \\

  • { 替換爲 \{

  • } 替換爲 \}

  • short

  • size

  • 序列中子變量的數量(作爲數字值)。假設序列中至少有一個子變量, 那麼序列 s 中最大的索引是 s?size - 1 (因爲第一個子變量的序列是0)。

  • sort

  • 以升序方式返回序列。(要使用降序排列時,使用它之後使用 reverse 內建函數。) 這僅在子變量都是字符串時有效,或者子變量都是數字,或者子變量都是日期值 (日期,時間,或日期+時間),或者所有子變量都是布爾值時(從2.3.17版本開始)。 如果子變量是字符串,它使用本地化(語言)的具體單詞排序(通常是大小寫不敏感的)。比如:

  • seq_contains

  • 辨別序列中是否包含指定值。它包含一個參數,就是來查找的值。比如:

  • seq_index_of

  • 返回序列中第一次出現該值時的索引位置, 如果序列不包含指定的值時返回 -1。 要查找的值作爲第一個參數。比如這個模板:

  • seq_last_index_of

  • sort_by

  • 返回由給定的哈希表子變量來升序排序的哈希表序列。 (要降序排列使用該內建函數後還要使用 reverse 內建函數。) 這個規則和 sort 內建函數 是一樣的, 除了序列中的子變量必須是哈希表類型,而且你不得不給哈希變量的命名, 那會用來決定排序順序。比如:

  • split

  • 它被用來根據另外一個字符串的出現將原字符串分割成字符串序列。 比如:

  • starts_with

  • 如果字符串以指定的子字符串開頭,那麼返回true。 比如 "redirect"?starts_with("red") 返回布爾值 true,而且 "red"?starts_with("red") 也返回 true

  • string: for stringsfor numbersfor booleansfor date/time/date-time

  • substring (deprecated)

  • switch

  • then

  • time for date/time/date-timefor strings

  • time_if_unknown

  • trim

  • 去掉字符串首尾的空格。例如:

  • uncap_first

  • 和 cap_first 相反。 字符串中所有單詞的首字母小寫。

  • upper_abc

  • 和 lower_abc 相同, 但是它轉換成大寫字母,比如 "A", "B", "C",… , "AA", "AB", 等...

  • upper_case

  • 字符串的大寫形式。比如 "GrEeN MoUsE" 將會是 "GREEN MOUSE".

  • url

  • 在URL之後的字符串進行轉義。這意味着, 所有非US-ASCII的字符和保留的URL字符將會被 %XX 形式轉義。例如:

  • values

  • 一個包含哈希表中子變量的序列。 注意並不是所有的哈希表都支持這個 (詢問程序員一個指定的哈希表是否允許這麼操作)。

  • 至於返回的值的順序,和內建函數 keys 的應用是一樣的;看看上面的敘述就行了。

  • word_list

  • 包含字符串中所有單詞的序列,順序爲出現在字符串中的順序。 單詞是不間斷的字符序列,包含了任意字符,但是沒有 空白。例如:

  • xhtml

  • 字符串作爲XHTML格式文本,下面這些:

  • < 替換爲 &lt;
  • > 替換爲 &gt;
  • & 替換爲 &amp;
  • " 替換爲 &quot;
  • ' 替換爲 &#39;
  • xml

  • 字符串作爲XML格式文本,下面這些:

  • < 替換爲 &lt;
  • > 替換爲 &gt;
  • & 替換爲 &amp;
  • " 替換爲 &quot;
  • ' 替換爲 &apos;

1.2 字符串內建函數

1.3 數字內建函數

1.4 日期內建函數

1.5 布爾值內建函數

1.6 序列內建函數

1.7 哈希表內建函數

1.8 結點(對於XML)內建函數

1.9 循環變量內建函數

1.10 獨立類型內建函數

switch

1.11 很少使用的和專家級的內建函數

2.指令參考

  • Alphabetical index

  • 基於 FreeMarker 2.3.23,對指令名可以使用駝峯形式來代替全小寫形式, 比如 noParse 來代替 noparse。 但是要知道在相同的模板中,FreeMarker 對所有標識符會強制使用駝峯形式, 這是模板語言的一部分(用戶自定義名稱不受影響)。

  • assign

  • 概要

  • 描述

  • 使用該指令你可以創建一個新的變量, 或者替換一個已經存在的變量。注意僅僅頂級變量可以被創建/替換 (也就是說你不能創建/替換 some_hash.subvar, 除了 some_hash)。

  • attempt

  • 概要
  • 描述
  • 如果你想讓頁面成功輸出內容,儘管它在頁面特定位置發生錯誤也這樣, 那麼這些指令就是有用的。如果一個錯誤在 attempt block 執行期間發生, 那麼模板執行就會中止,但是 recover block 會代替 attempt block 執行。 如果在 attempt block 執行期間沒有發生錯誤, 那麼 recover block 就會忽略。 一個簡單的示例如下:

  • 在 recover block 塊中,錯誤的信息存在 特殊變量 error 中。 不要忘了以點開始引用特殊變量(比如:${.error})。

    在模板執行期間發生的錯誤通常被 日誌記錄,不管是否發生在 attempt block塊中。

  • compress

  • 概要
  • 描述
  • flush

  • 概要
  • 描述
  • ftl

  • 概要
  • 描述
  • 告訴 FreeMarker 和其他工具關於模板的信息, 而且幫助程序員來自動檢測一個文本文件是否是 FTL 文件。該指令, 如果存在,必須是模板的第一句代碼。該指令前的任何 空白 將被忽略。 該指令的老式語法(#-less)格式是不支持的。

  • 一些設置(編碼方式,空白剝離等)在這裏給定的話就有最高的優先級, 也就是說,它們直接作用於模板而不管其他任何 FreeMarker 的配置設置。

  • function, return

  • 概要
  • 描述
  • 創建一個方法變量(在當前命名空間中,如果你知道命名空間的特性)。 這個指令和 macro 指令 的工作方式一樣,除了 return 指令必須有一個參數來指定方法的返回值,而且視圖寫入輸出的將會被忽略。 如果到達 </#function> (也就是說沒有 return returnValue), 那麼方法的返回值就是未定義變量。

  • global

  • 概要
  • 描述
  • if, else, elseif

  • 概要
  • 描述
  • 你可以使用 if, elseif 和 else 指令來條件判斷是否越過模板的一個部分。 condition 必須計算成布爾值, 否則錯誤將會中止模板處理。elseif 和 else 必須出現在 if 內部 (也就是,在 if 的開始標籤和結束標籤之間)。 if 中可以包含任意數量的 elseif(包括0個) 而且結束時 else 是可選的。比如:

  •  

  • import

  • 概要
  • 描述
  • 引入一個庫。也就是說,它創建一個新的空命名空間, 然後在那個命名空間中執行給定 path 參數中的模板, 所以模板用變量(宏,函數等)填充命名空間。 然後使得新創建的命名空間對哈希表的調用者可用。 這個哈希表變量將會在命名空間中,由 import (就像你可以用 assign 指令來創建一樣。) 的調用者被創建成一個普通變量,名字就是 hash 參數給定的。

  • include

  • 概要
  • 描述
  • 你可以使用它在你的模板中插入另外一個 FreeMarker 模板文件 (由 path 參數指定)。 被包含模板的輸出格式是在 include 標籤出現的位置插入的。 被包含的文件和包含它的模板共享變量,就像是被複制粘貼進去的一樣。 include 指令不能由被包含文件的內容所替代, 它只是當 FreeMarker 每次在模板處理期間到達 include 指令時處理被包含的文件。所以對於如果 include 在 list 循環之中的例子, 你可以爲每個循環週期內指定不同的文件名。
  • path 參數可以是如 "foo.ftl" 和 "../foo.ftl" 一樣的相對路徑,或者是如 "/foo.ftl" 這樣的絕對路徑。 相對路徑是相對於使用 import 指令的模板文件夾。 絕對路徑是相對於程序員在配置 FreeMarker 時定義的基路徑 (通常指代"模板的根路徑")。
  • 通常使用 /(斜槓)來分隔路徑成分, 而不是 \(反斜槓)。如果你從你本地的文件系統加載模板, 而它使用反斜槓(像Windows操作系統),也要使用 /
    • 使用獲得機制
    • 有一個特殊的路徑組成,是用一個星號(*)來代表的。 它被解釋爲"當前目錄或其他任意它的父目錄"。因此, 如果模板在 /foo/bar/template.ftl 位置上,有下面這行

    • <#include "*/footer.ftl">

    • 那麼引擎就會在下面的位置上尋找模板,並按這個順序:

    • /foo/bar/footer.ftl
    • /foo/footer.ftl
    • /footer.ftl
    • 該機制被稱爲 acquisition 並允許設計者在父目錄中放置通用的被包含的文件, 而且當需要時在每個子路徑基礎上重新定義它們。 我們說包含它們的模板獲得了從包含它的第一個父目錄中的模板。請注意, 你不但可以在星號的右面指定一個模板的名字,也可以指定一個子路徑。 也就是說,如果前面的模板由下面這個所替代:
    • <#include "*/commons/footer.ftl">
    • 那麼引擎將會從下面的路徑開始尋找模板,並按這個順序:

    • /foo/bar/commons/footer.ftl
    • /foo/commons/footer.ftl
    • /commons/footer.ftl
    • 最終,星號不再是路徑的第一個元素:
    • <#include "commons/*/footer.ftl">
    • 會讓引擎將會從下面的路徑開始尋找模板,並按這個順序:

    • /foo/bar/commons/footer.ftl
    • /foo/bar/footer.ftl
    • /foo/footer.ftl
    • /footer.ftl
    • 然而,在路徑中最多只能有一個星號。 指定多餘一個星號會導致模板不能被發現。
    • 本地化查找
    • 本地化是語言和可選的國家或方言標識符 (加上可能的更多變體標識符,比如 "MAC")。 無論何時模板被請求,期望的本地化都會被指定(明確或含蓄), FreeMarker 會試圖找到變化的模板來匹配本地化環境。當模板包含或引入其它模板時, 在內部也會被請求一個本地化環境,也就是 locale 配置的本地化, 通常它是頂級模板的本地化設置。

    • 假設模板使用本地化 en_US 來加載, 就是美國英語。當包含其它模板時:

    • <#include "footer.ftl">
    • 引擎實際上就會尋找一些模板,並按照這個順序:

    • footer_en_US.ftl,
    • footer_en.ftl
    • footer.ftl
    • 它會使用第一個存在的。
    • 請注意,如果 FreeMarker 查找的本地化變化是由程序員配置的, 那麼這裏我們只能描述默認的行爲。 可以使用 localized_lookup 設置來禁用本地化查找 (Configuration.setLocalizedLookup(boolean))。 而且,可以使用 template_lookup_strategy 設置來自行定義推導出的模板名稱序列 (Configuration.setTemplateLookupStrategy(TemplateLookupStrategy))。
    • 當你同時使用獲得機制(也就是路徑中的 * 步驟) 和本地化查找時,在父目錄中有指定本地化的模板優先於在子目錄中有很少本地化的模板。 假設你使用下面的代碼來包含 /foo/bar/template.ftl
    • 引擎將會查找這些模板,並按照這個順序:

    • /foo/bar/footer_en_US.ftl
    • /foo/footer_en_US.ftl
    • /footer_en_US.ftl
    • /foo/bar/footer_en.ftl
    • /foo/footer_en.ftl
    • /footer_en.ftl
    • /foo/bar/footer.ftl
    • /foo/footer.ftl
    • /footer.ftl
  • list, else, items, sep, break

  • 概要
  • 描述
  • local

  • 概要
  • 描述
  • macro, nested, return

  •  

  • 概要
  • 描述
  • 創建一個宏變量(在當前命名空間中,如果你知道命名空間的特性)。 如果你對宏和自定義指令不瞭解,你應該閱讀 自定義指令指南
  • 宏變量存儲模板片段(稱爲宏定義體)可以被用作 自定義指令。 這個變量也存儲自定義指令的被允許的參數名。當你將這個變量作爲指令時, 你必須給所有參數賦值,除了有默認值的參數。 默認值當且僅當你調用宏而不給參數賦值時起作用。
  • 變量會在模板開始時被創建;而不管 macro 指令放置在模板的什麼位置。因此,這樣也可以:
  • nested
  • nested 指令執行自定義指令開始和結束標籤中間的模板片段。 嵌套的片段可以包含模板中任意合法的內容:插值,指令等...它在上下文環境中被執行, 也就是宏被調用的地方,而不是宏定義體的上下文中。因此,比如, 你不能看到嵌套部分的宏的局部變量。如果你沒有調用 nested 指令, 自定義指令開始和結束標記中的部分將會被忽略。
  • return
  • noparse

  • 概要
  • 描述
  • nt

  • setting

  • 概要
  • 描述
  • 爲進一步的處理而設置。設置是影響 FreeMarker 行爲的值。 新值僅僅在被設置的模板處理時出現,而且不觸碰模板本身。 設置的初始值是由程序員設定的 (參考: 程序開發指南/配置(Configuration)/配置設置)。

  • stop

  • switch, case, default, break

  •  

  • 概要
  • 描述
  • 這個指令的用法是不推薦的,因爲向下通過的行爲容易出錯。使用 elseif來代替, 除非你想利用向下通過這種行爲。

  • Switch 被用來選擇模板中的一個片段,如何選擇依賴於表達式的值:

  • 在 switch 中間必須有一個或多個 <#case value>, 在所有 case 標籤之後,有一個可選的 <#default>。 當FreeMarker到達 switch 指令時,它會選擇一個 case 指令,這裏的 refValue 等於 value 並且繼續模板處理。 如果沒有和合適的值匹配的 case 指令,那麼就繼續處理 default 指令,如果它存在,否則就繼續處理 switch 結束標籤之後的內容。現在有一個混亂的事情: 當它選擇一個 case 指令後,它就會繼續處理其中的內容, 直到遇到 break 指令。也就是它遇到另外一個 case 指令或 <#default> 標記時也不會自動離開 switch 指令。比如:

  • t, lt, rt

  • 概要
  • 描述
  •  

  • User-defined directive (<@...>)

  • 概要
  • 描述
  • 這將調用用戶自定義指令,比如宏。參數的含義, 支持和需要的參數的設置依賴於具體的自定義指令。
  • 結束標籤
  • 你可以在 結束標籤 中忽略 user_def_dir_exp。 也就是說,你可以寫 </@> 來替代 </@anything>。 這個規則當表達式 user_def_dir_exp 太複雜時非常有用,因爲你不需要在結束標籤中重複表達式。 此外,如果表達式包含比簡單變量名和點還多的表達式,你就不能再重複它們了。比如, <@a_hash[a_method()]>...</@a_hash[a_method()]> 就是錯的,你必須寫爲 <@a_hash[a_method()]>...</@>。 但是 <@a_hash.foo>...</@a_hash.foo> 是可以的。

    • 循環變量
    • 位置參數傳遞
    • 位置參數傳遞(如<@heading "Preface", 1/>) 是正常命名參數傳遞(如<@heading title="Preface" level=1/>) 的速記形式,這裏忽略了參數的名稱。如果自定義指令只有一個參數, 或者對於經常使用的自定義指令它參數的順序很好記憶,速記形式應該被應用。 爲了應用這種形式,你不得不瞭解聲明的命名參數的順序(如果指令只有一個參數這是很瑣碎的)。 也就是,如果 heading 被創建爲 <#macro heading title level>..., 那麼 <@heading "Preface", 1/> 和 <@heading title="Preface" level=1/> (或 <@heading level=1 title="Preface"/>; 如果你使用參數名稱,那順序就不重要了)是相等的。 要注意位置參數傳遞現在僅僅支持宏定義。

  • visit, recurse, fallback

  •  

  • 概要
  • 描述
  • visit 和 recurse 指令是用來遞歸處理樹的。在實踐中,這通常被用來 處理XML

    • Visit
    • Recurse
    • <#recurse> 指令是真正純語義上的指令。 它訪問結點的所有子結點(而沒有結點本身)。所以來寫:

    • Fallback

3.特殊變量參考

特殊變量是由FreeMarker引擎自己定義的變量。要訪問它們, 你可以使用 .variable_name 語法。 比如,你不能僅僅寫 version,而必須寫.version

4.FTL 中的保留名稱

下面的這些名稱不能在非方括號語法中被用作頂層變量 (比如 .vars["in"]),因爲這是FTL中的關鍵字:

  • true:布爾值"true"
  • false:布爾值"false"
  • gt:比較運算符"大於"
  • gte:比較運算符"大於或等於"
  • lt:比較運算符"小於"
  • lte:比較運算符"小於或等於"
  • as:由少數指令使用
  • in:由少數指令使用
  • using:由少數指令使用

5.廢棄的 FTL 結構

 

下面這些指令不再可以運行:

  • 廢棄的指令列表
  • 下面這些指令是廢棄的,但是仍然可以運行:

  • call:使用 自定義指令調用 來代替。

  • comment:這是 <#--...--> 的老格式。 在 <#comment> 和 </#comment> 之間的任何東西都會被忽略。

  • foreach: 它是 list 指令的代名詞,有着略微不同的參數語法。它的語法結構是 <#foreach item in sequence>,和 <#list sequence as item>是相同的。

  • transform: 使用 自定義指令調用 來代替

  • 遺留的 function:起初 function 是被用作定義宏,現在由 macro 指令完成,它就被廢棄了。 對於 FreeMarker 2.3 版本來說,這個指令由於不同的意義而再次引入: 它被用來定義方法。

  • 廢棄的內建函數列表
  • 下面這些內建函數是被廢棄的,但是仍可以運行:

  • default:由於 默認值操作符 的引入,它被廢棄了。exp1?default(exp2) 和 exp1!exp2 是相同的, (exp1)?default(exp2) 和 (exp1)!exp2 是相同的。 唯一的不同是在 FreeMarker 2.4 版本之前,內建函數 default 通常算作是 exp2,而默認值操作符僅僅當默認值真的需要時纔算。 從 FreeMarker 2.4 版本之後,內建函數 default 被改進了, 和默認值運算符的行爲非常像了。

  • exists:由於 空值測試操作符 的引入,它被廢棄了。 exp1?exists 和 exp1?? 是一樣的, (exp1)?exists 和 (exp1)?? 也是一樣的。

  • if_exists:由於 默認值操作符 的引入,它被廢棄了。 exp1?if_exists 和 exp1! 相似, (exp1)?if_exists 和 (exp1)! 相似。不同之處在於, 用 if_exists 的默認值不僅僅同時是空字符串,空序列和空哈希表, 而且布爾值 false 和不做任何事情的變換,還有忽略所有參數。

  • web_safe:和 html 相同。

  • 老式的 macro 和 call 指令
  • 概要
  • 描述
  • 宏是關聯名稱的模板段。你可以在你的模板中的很多位置使用命名的代碼段, 所以它可以在重複的任務中幫助你。宏可以有參數,這會在你調用它的時候影響生成的輸出。

  • 你可以使用 macro 指令來定義宏,之後你可以在整個模板中定義宏。 macro 指令本身不往輸出中寫任何東西,它只是用來定義宏。 例如這會定義一個名爲 warning 的宏:

  • 轉換指令
  • 概要
  • 描述

捕捉生成在它體內(也就是開始標籤和結束標籤之間)的輸出, 之後讓給定的轉換物在寫入最終的輸出之前改變。

  • 老式 FTL 語法
  • 在FTL標籤中使用 # 形式的FTL語法已經是不要求 (在 2.1 版本之前是不允許的)的了。比如,你可以這樣寫代碼:

    <html>
    <head>
      <title>Welcome!</title>
    </head>
    <body>
      <h1>Welcome ${user}!</h1>
      <p>We have there animals:
      <ul>
      <list animals as animal>
        <li>${animal.name} for ${animal.price} Euros
      </list>
      </ul>
      <include "common_footer.html">
    </body>
    </html>

    而沒有 # 樣式語法的代碼對於HTML作者來說更加自然, 它有很多的缺點,所以最終我們決定廢棄它。使用新式語法(又稱爲"嚴格的語法"), # 是嚴格要求的。也就是說,像 <include "common_footer.html"> 這樣的東西將會原樣出現在輸出中,因爲它們不被認爲是FTL標籤。 注意用戶自定義指令使用 @ 代替 #

    然而,爲了給用戶時間來準備這種改變,在 FreeMarker 2.1 和 2.2 版本中, # 的用法是可選的,除非程序員調用 Configuration 的 setStrictSyntaxMode(true) 在 FreeMarker 配置中開啓嚴格語法模式。 事實上,我們把這個強烈建議給程序員。從後續釋出版本開始,這個設置將會初始設置爲 true。而且,如果你在模板文件中想使用嚴格語法或老式語法,你可以用 ftl 指令來指定。

    "嚴格語法"比遺留的FTL語法的好處是:

  • 對於FTL來說,所有 <#...> 和 </#...> 都是保留的:

    • 我們可以引入新的指令而不破壞向後兼容。

    • 我們可以檢測你是否創留了一個打字錯誤,也就是 <#inculde ...> 被視爲解析時的錯誤, 而不是被靜默地視爲簡單文本。

    • 對於第三方工具來處理模板(比如高亮語法顯示)來說是簡單的, 特別是因爲它們不需要知道新釋出版本中被引入的新指令。

    • 模板更易於閱讀,因爲很容易辨認嵌入在HTML或其他標記中的 <#...> 標籤。

  • <# 和 </# 是合法的XML (除了在CDATA段中),而且其他大多數SGML應用中也是合法的, 所以它們不能妨礙用在靜態文本部分(比如你在生成的XML中有 include 元素)的標籤。

  • #{...}: 數字插值
  • 已經被廢棄了:使用 number_format 設置項 和 the string 內建函數 來代替。對於計算機使用 (也就非本地的格式化)的格式化,使用 c 內建函數 (比如 number?c)。

  • 概要
  • 描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章