Configuration 是一個存放應用級別(application level)公共配置信息,以及模版(Template)可以使用的全局共享變量的一個對象。同時它還負責模版(Template)實例的建立以及緩存。Configuration 其實是freemarker.template.Configuration 對象的實例,使用其構造函數建立。一般應用使用一個共享的單實例Configuration 對象。 java
Configuration 對象可被Template 對象的方法使用,每個模版實例都關聯與一個Configuration 實例,它是經過Template 的構造函數被關聯進去的,一般是你使用這個方法來Configuration.getTemplate 得到模版對象的。 web
共享變量是那些定義給全部模版(Template)使用的變量。你能夠經過configuration對象的setSharedVariable 方法來添加共享變量。 緩存
Configuration cfg = new Configuration(); ... cfg.setSharedVariable("wrap", new WrapDirective()); cfg.setSharedVariable("company", "Foo Inc."); // Using ObjectWrapper.DEFAULT_WRAPPER
全部與該configuration 對象關聯的模版實例都就能夠經過得到to_upper 轉換器,company 來得到字符串,所以你不須要再一次次的往root 中添加這些變量了。若是你往root 添加同名的變量,那麼你新添加的變量將會覆蓋以前的共享變量。 安全
警告! 多線程
若是configuration 對象被多線程調用,那麼不要使用TemplateModel 實現類做爲共享變量,由於他們是非線程安全的,例如基於servlet 的web 站點就是這種狀況。 app
Configuration 對象初始化時已經包含一些共享轉換器變量: ide
名字類 函數
name | class |
---|---|
capture_output | freemarker.template.utility.CaptureOutput |
compress | freemarker.template.utility.StandardCompress |
html_escape | freemarker.template.utility.HtmlEscape |
normalize_newlines | freemarker.template.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} <#setting locale="en_US"> ${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 層的配置
freemarker.template.Configuration.setSetting(String,String)
模版加載器
模版加載器是基於抽象路徑("index.ftl"或"products/catalog.ftl")加載原始數據的那些對象,而究竟加載何種資源(目錄中的文件數據仍是數據庫中的數據)取決於具體的加載器實現。當你調用cfg.getTemplate 時,FreeMarker 將會詢問你以前配置給Configuration 對象的模版加載器,有該模版加載器負責文件的載入。
內建的模版加載器
你能夠用如下三個方法來設置模版加載的三種方式
void setDirectoryForTemplateLoading(File dir);
或者
void setClassForTemplateLoading(Class cl, String prefix);
或者
void setServletContextForTemplateLoading(Object servletContext, String path);
以上第一種方式顯示的指定了一個文件系統中的目錄,FreeMarker 將會在此目錄記載模版,不用說,此目錄必須存在,否在會拋出異常。
第二種方式以一個Class做爲一個輸入參數,當你想使用ClassLoader的方式來加載模版的時候,你就可使用這種方式,這種方式將會調用來尋找模版文件,同時這種模版加載的方式要比前一種穩定一些尤爲是在生產系統中。你能夠很容易的把資源文件,以及圖標等打包到.jar 文件中。
第三種方式把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[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl }; MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); cfg.setTemplateLoader(mtl);
FreeMarker 將會首先在路徑/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_KEY,"strong:20, soft:250");
當你建立一個新的Configuration時,其默認使用MruCacheStorage緩存實現且默認的值maxStrongSize等於0,maxSoftSize等於Integer.MAX_VALUE(也就是理論最大值)。可是對於高負荷的系統來講,咱們建議maxStrongSize 設置成一個非0 的數值,否則會致使頻繁的從新加載,從新解析模版。
可能產生的異常
FreeMarker 產生的異常通常可歸如下幾類:
FreeMarker 初始化階段產生的異常: 一般在你的應用中僅須要初始化FreeMarker 一次,而當在這個時間段類產生的異常就叫作初始化異常。
加載解析模版期的異常:當你經過Configuration.getTemplate()方法獲取模版的時候(若是模版以前沒有被緩存),將會產生兩類異常:
執行期間的異常:當你調用Template.process(...)方法的時候,會拋出兩類異常:
原文由motomagice@yahoo.com.cn翻譯自FreeMarker官方手冊《Programmer's Guide》。