1. 程式人生 > >【FreeMarker】【程式開發】資料模型,物件包裝

【FreeMarker】【程式開發】資料模型,物件包裝

在簡單的示例中,可以使用 java.lang 和 java.util 包下的類,還有使用者自定義的 Java Bean來構建資料物件。

  • 使用 java.lang.String 來構建字串
  • 使用java.lang.Number 來派生數字型別
  • 使用 java.lang.Boolean 來構建布林值
  • 使用 java.util.List 或 Java 陣列構建序列
  • 使用 java.util.Map 來構建雜湊表
  • 使用自定義的 bean 類來構建雜湊表,bean中的項和bean的屬性對應

資料模型

在內部,模板中可用的變數都是實現了 freemarker.template.TemplateModel 介面的 java 物件。

但在自己的資料模型中,可以使用基本的Java集合類作為變數,因為這些變數會在內部被替換為適當的 TemplateModel 型別;這種功能特性被稱為 object wrapping 物件包裝

物件包裝功能可以透明地把任何型別的物件轉換為實現了 TemplateModel 介面型別的例項。

這就是的下面的轉換成為可能,如在模板中 java.sql.ResultSet 轉換為序列變數,把 javax.servlet.ServletRequest 物件轉換成包含請求屬性的雜湊表變數,甚至可以遍歷 XML 文件作為 FTL變數。

包裝這些物件,需要使用合適的,也就是所謂的物件包裝器是錢(也可能是自定義的實現)。

標量

4中型別的變數:

  • 布林值 —— 實現TemplateBooleanModel介面
  • 數字 —— 實現TemplateNumberModel介面
  • 字串 —— 實現TemplateScalarModel介面
  • 日期 —— 實現TemplateDateModel介面

容器

雜湊表

FreeMarker中的雜湊表是實現了 TemplateHashModel 介面的物件。TemplateHashModelEx介面擴充套件了TemplateHashModel介面;經常使用的實現類是SimpleHash,該類實現了TemplateHashModelEx介面。

序列

序列是實現了TemplateSequenceModel介面的Java物件。經常使用的實現類是SimpleSequence。

集合

集合是實現了TemplateCollectionModel介面的Java物件。通常使用的實現類是SimpleCollection。

方法

方法變數實現了 TemplateMethodModel 介面。這個介面僅包含一個方法:TemplateModel exec(java.util.List arguments),當使用方法呼叫表示式去呼叫方法時,exec方法將會被呼叫。形參將會包含FTL方法呼叫形參的值,exec方法的返回值給出了FTL方法呼叫表示式的返回值。

TemplateMethodModelEx介面擴充套件了TemplateMethodModel介面。

例如:

public class IndexOfMethod implements TemplateMethodModel {
    public TemplateModel exec(List args) throws TemplateModelException {
        if (args.size() != 2) {
            throw new TemplateModelException("Wrong arguments");
        }
        return new SimpleNumber(
               ((String) args.get(1)).indexOf((String) args.get(0)));
    }
}

將一個方法例項放入根資料模型中,

root.put("indexOf", new IndexOfMethod());

在模板中呼叫:

<#assign x = "something">
${indexOf("met", x)}
${indexOf("foo", x)}

輸出為:

2
-1


指令@

指令變數實現了TemplateDirectiveModel介面。

節點變數

節點變數體現了樹形結構中的節點。節點變數的引入是為了幫助使用者在資料模型中處理XML文件,也可以使用者構建樹狀模型。

節點變數實現TemplateNodeModel介面。

物件包裝

當往容器中新增一些物件時,可以是任意java物件型別的引數,而不一定是TemplateModel。這是因為模板實現會默默地用合適的TemplateModel物件來替換原有物件。比如向容器中加入一個String,也許它將被替換為一個SimpleScalar例項來儲存相同的文字。

至於什麼型別的Java物件可以被替換,又使用什麼樣的TemplateModel來實現,它可以被實現的容器自身來控制,也可以委派給ObjectWrapper的一個例項。

ObjectWrapper是一個介面,其中只定義了一個方法:TemplateModel wrap(java.lang.Object obj)。可以傳遞一個object型別的物件,它會返回對應的TemplateModel物件,如果不行則丟擲TemplateModelException一場。替換原則是在ObjectWrapper的實現類中編碼實現的。

最重要的ObjectWrapper實現類是FreeMarker核心包提供的:

public interface ObjectWrapper {

    ObjectWrapper BEANS_WRAPPER = BeansWrapper.getDefaultInstance();

    ObjectWrapper DEFAULT_WRAPPER = DefaultObjectWrapper.instance;

    ObjectWrapper SIMPLE_WRAPPER = SimpleObjectWrapper.instance;

我們使用java.util.HashMap作為根的雜湊表,而不是SimpleHash或其他特定的FreeMarker類,因為Template.process(...)自動包裝了給定的資料模型引數的物件,所以它才會起作用。它使用受Configuration設定的物件包裝器。因此,編寫簡單的FreeMarker應用程式就不需要知道TemplateModel。注意根的型別不需要一定是java.util.Map,它也可以是實現了TemplateHashModel介面的被包裝的物件。