p> 基礎
Configuration 是一個存放應用層級(application level)公共配置訊息,以及模版(Template)可使用的全域共享變數的物件。同時它還負責模版(Template)實例的建立以及快取。 Configuration 其實是freemarker.template.Configuration 物件的實例,使用其建構子建立。通常會應用使用一個共享的單實例Configuration 物件。
Configuration 物件可被Template 物件的方法使用,每個模版實例都關聯與一個Configuration 實例,它是透過Template 的建構子被關聯進去的,通常是你使用這個方法來Configuration.getTemplate 取得模版物件的。
共享變數
共享變數是那些定義給所有模版(Template)使用的變數。你可以透過configuration物件的setSharedVariable 方法來新增共享變數。
Configuration cfg = new Configuration(); ... cfg.setSharedVariable("wrap", new WrapDirective()); cfg.setSharedVariable("company", "Foo Inc."); // Using ObjectWr.PERP.
所有與該configuration 物件關聯的模版實例都可以透過取得to_upper 轉換器,company 來取得字串,因此你不需要再一次次的往root 中新增這些變數了。如果你往root 新增同名的變量,那麼你新加入的變數將會覆蓋先前的共享變數。
警告!
如果configuration 物件被多線程調用,那麼不要使用TemplateModel 實作類別作為共享變量,因為他們是非線程安全的,例如基於servlet 的web 站點就是這種情況。
Configuration 物件在初始化時已經包含一些共享轉換器變數:
名字類別
name class capture_output freemarker.template.utility.CaptureOutput compress freemarker.template.utility.Compress html_e. .utility.NormalizeNewlines xml_escape freemarker.template.utility.XmlEscape
配置參數
配置參數是那些可以影響FreeMarker 運作行為的那些命名參數。例如locale,number_format。
配置參數儲存在Configuration實例中,它可以被模版實例(Template)修改。例如,你在Configuration中設定了locale等於"en_US",那麼所有的模版物件都會使用,"en_US"除非你在單一模版實例中利用setLocale方法修改了預設設定。因此configuration設定的參數可以當作是預設參數,它可以被Template一級設定的參數覆蓋,而它們兩者設定的參數資訊又可以被環境中設定的參數所覆蓋(也就是模版檔案指令設定的)如下:
${1.2}${1.2}
這種調用方式你可以想像成3 個層(配置物件層,模版層,運行環境層)下面表格中顯示了每一層對於參數的設定:
Setting A Setting B Setting C Setting D Setting E Setting F Layer 3:Environment 1 - - 1 - - Layer 2:Template 2 2 - - 2 - Layer 1:Configuration 3 3 3 3 - -
那麼配置參數的最終結果分別是:A = 1, B = 2, C = 3, D = 1, E = 2.而F 參數很可能就是null。
如果要查詢可設定的參數列表,你可以查閱FreeMarker API 文件的以下兩個部分:
所有層的配置
freemarker.core.Configurable.setSetting(String, String)
Coniguration 層的配置配置
Coniguration 層的配置。 freemarker.template.Configuration.setSetting(String,String)載入範本
你可以用以下三個方法來設定模版載入的三種方式
第三種方式把web 應用的上下文以及基底路徑(相對與WEN-INF 的父路進來說)當作參數。該種方式的模版載入器將會從web 應用上下文種載入模版。
從多個位置加載模版
如果你想從多個位置加載模版的話,你可以分別創建與不同位置對應的單個模版加載器,然後把它們包裹到一個名叫MultiTemplateLoader透過方法setTemplateLoader(TemplateLoader loader)把其設定給Configuration 對象,以下有一個從兩個不同位置載入模版的例子:
import freemarker.cache.*; // template loaders live in this package ... FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates")); FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates")); ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); TemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); TemplateLoader [] loaders = new TemplateLoader[] { ftl1, ftl2, ctl }; MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); cfg.setTemplateLoader(mtl);
FreeMarker 將會先在路徑/tmp/templates/tmp/templates沒有找到那麼回到路徑/usr/data/templates中搜索,如果還沒找到,那麼則會嘗試用class-loader的方式載入。
從其他資源中取得模版檔案
如果在這些內建的模版載入器中沒有一個符合你的要求,那麼你可以自己自訂一個模版載入器,只需要實作freemarker.cache.TemplateLoader 介面就可以了,然後透過方法setTemplateLoader(TemplateLoader loader)把其傳遞給Configuration物件。
快取模版
FreeMarker快取模版的意思是,當你透過getTemplate方法取得一個模版的時候,FreeMarker不僅會返回一個Template對象,而且會快取該對象,當你下一次以相同的路徑請求模版的時候,它就會傳回快取中的模版物件。如果你改變了模版文件,那麼當你下次取得模版的時候,FreeMarker會自動重新載入,重新解析模版。雖然如此,但是如果直接判斷一個檔案是否修改過是一個耗時的操作,那麼FreeMarker 在Configuration 物件層級提供了一個設定參數「update delay」。這個參數的意思是FreeMarker多久去判斷一次模版的版本,預設設定是5秒鐘,也就是每個5秒就會判斷模版是否經過修改,如果你想即時的判斷,那麼設定該參數為0 。另外一點要注意,並不是所有的載入器都支援這種判斷方式,舉例來說基於class-loader 的模版載入器就不會發現你修改過模版檔案。
對於刪除快取中的模版FreeMarker 是這麼做的,你可以使用Configuration 物件方法clearTemplateCache 以手工的方式清楚快取中的模版物件。而實際上快取部分可以作為一個組成加入到FreeMarker 中(也就是它可以使用第三方快取方案)你可以透過設定cache_storage 這個參數來實現。對大多數開發者來FreeMarker 自帶的freemarker.cache.MruCacheStorage 實作已經足夠了。這個快取使用2 個等級的Most Recently Used(最近最多使用)策略。在第一個級別,所有的快取條目都是使用強引用(strongly referenced:條目並不會被JVM 所清楚,與其相對的弱引用softly reference)直到達到最大時間,那些最近最少使用的條目就會被遷移到二級快取。在這個等級條目都是使用弱引用直到達到過期。若引用與強引用的區域的大小是可以在建構函式中設定的,例如你想把強引用區域設為20,弱引用區域設定為250,那你可以使用以下程式碼:
cfg.setCacheStorage(new freemarker.cache.MruCacheStorage(20, 250))
由於MruCacheStorage 是預設的快取實現,那麼你也可以這樣設定:
cfg.setSetting(Configuration.CACHE_STORAGE_KEYEY"strong:20, softration
";當你建立一個新的Configuration時,其預設使用MruCacheStorage快取實作且預設的值maxStrongSize等於0,maxSoftSize等於Integer.MAX_VALUE(也就是理論最大值)。但是對於高負載的系統來說,我們建議maxStrongSize 設定成一個非0 的數值,不然會導致頻繁的重新加載,重新解析模版。
異常處理
可能產生的異常
FreeMarker 產生的異常一般可歸以下幾類:
FreeMarker 初始化階段產生的異常: 通常在你的應用中僅需要初始化FreeMarker 一次,而當在這個時間段類別產生的異常就叫做初始化異常。
載入解析模版期的異常:當你透過Configuration.getTemplate()方法取得模版的時候(如果模版之前沒有被快取),將會產生兩類異常:
IOException:由於模版沒有找到,或在讀取模版的時候發生其他的IO異常,例如你沒有讀取該檔案的權限等等;freemarker.core.ParseException 由於模版檔案的語法使用不正確;
執行期間的例外:當你呼叫Template.process(...)方法的時候,會拋出兩類異常:
IOException 往輸出寫資料時發生的錯誤;freemarker.template.TemplatException其他運行期產生的異常,例如一個最常見的錯誤就是模版引用了一個不存在的變數;
更多FreeMarker配置(Configuration)相關文章請關注PHP中文網!