FreeMarker是一個模版引擎,一個基于模版生成文本輸出的通用工具,使用純Java編寫。FreeMarker被設計用來生成HTML Web頁面,特別是基于MVC模式的應用程序。FreeMarker有一些編成能力,但通常情況下用java程序準備要顯示的數據,由FreeMarker生成頁面,通過模版顯示準備的數據。FreeMarker不是一個Web應用框架,而更適合作為一個Web應用框架的一個組件。FreeMarker與容器無關,它并不知道HTTP或者Servlet,FreeMarker同樣可以用于非Web應用環境。FreeMarker更適合Model2的視圖組件,同樣可以在模版中使用JSP標記庫。
FreeMarker的通用目標:能夠生成各種文本,HTML、XML、RTF、Java源代碼等等;易于嵌入,輕量級、不需要Servlet環境;插件式的模版載入器,可以在任何源載入,如本地文件、數據庫等等;按需生成文本,保存到本地文件、作為Email發送、從Web應用程序發送它返回到Web瀏覽器。
強大的模版語言:所有常用的指令,include、if/elseif/else、循環結構。在模板中創建和改變變量。可以使用復雜的表達式來使用值。命名的宏,可以具有位置參數和嵌套內容。名字空間有助于建立和維護可重用的宏庫,或者將一個大的工程分為若干個模塊,而不必擔心命名的沖突。輸出轉換塊,在嵌套模版片斷生成輸出時,轉換HTML轉義、壓縮、語法高亮等等。。
通用的數據模型:FreeMarker不是直接反映到java對象,java對象通過插件式封裝,以變量的方式在模版中展示。使用抽象的方式表示對象,使其不受技術細節的打擾。
? 在模板語言中內建處理典型Web 相關任務(如HTML 轉義)的結構
? 能夠集成到Model2Web 應用框架中作為JSP 的替代
? 支持JSP 標記庫
? 為MVC 模式設計:分離可視化設計和應用程序邏輯;分離頁面設計員和程序員
5、智能的國際化和本地化
? 字符集智能化(內部使用UNICODE)
? 數字格式本地化敏感
? 日期和時間格式本地化敏感
? 非US 字符集可以用作標識(如變量名)
? 多種不同語言的相同模板
6、強大的XML 處理能力
? <#recurse> 和<#visit>指令(2.3 版本)用于遞歸遍歷XML 樹
? 在模板中清楚和直覺的訪問XML 對象模型
FreeMarker是一個Java模版語言,它是 JSP 的絕佳替代方案. FreeMarker在你的action result可能需要在Servlet容器環境以外被載入的情況下是理想選擇. 例如,如果你希望在你的應用程序中支持plugins,你可能會樂意使用Freemarker,因為那樣的話plugins可以支持將所有的action class和view都打包到一個從classloader進行裝載的jar文件里面.
關于FreeMarker的更多信息,請訪問FreeMarker網站.
FreeMarker與Velocity非常相似, 它們都是可以在Servlet容器外使用的模版語言. WebWork小組更推薦FreeMarker, 而不是Velocity, 這是因為FreeMarker提供了更好的錯誤報告, 支持JSP標簽, 稍多的功能. 當然, 這兩種技術都是代替JSP的很好方案.
快速上手
確認配置好你的項目的classpath中的所有依賴以后, 開始使用FreeMarker就非常簡單了. 典型情況下只需要 freemarker.jar. 除它以外, webwork-default.xml已經配置好了將FreeMarker Result映射到你的模版文件. 你現在可以試驗一下如下 xwork.xml 配置:
<action name="test" class="com.acme.TestAction">
<result name="success" type="freemarker">test-success.ftl</result>
</action
然后寫好 test-success.ftl:
<html>
<head>
<title>Hello</title>
</head>
<body>
Hello, ${name}
</body>
</html>
這里 name 是你的action中的一個屬性. 這樣就可以了! 該文檔的余下部分將介紹模版如何被加載, 變量如何解析, tags(標簽)也可以使用.
模版加載
Webwork在兩個位置查找FreeMarker模版(按順序):
Web應用程序目錄(Web application)
Class path
這個順序對于在完全編譯的jar中提供模版很理想, 但是也同時支持在Web應用程序目錄中定義這些模版來覆蓋jar中的模版文件. 事實上, 這就是為什么你可以覆蓋WebWork中默認的UI tags和Form Tags的原理.
還有, 你可以通過templatePath 上下文變量(context variable)指定一個路徑(你的文件系統中的一個目錄). 如果指定了該變量, 那么這個目錄中的內容將會被優先尋找.
變量解析/決定(Resolution)
在FreeMarker中, 變量將會在多個位置進行尋找, 順序如下:
值棧(value stack)
action上下文(action context)
Request范圍(scope)
Session范圍(scope)
Application范圍(scope)
內建變量
注意action上下文在value stack后進行搜索. 這意味著你可以引用變量而不必使用標準的符號(#)前綴,不像在JSP中使用ww:property中必須使用的那種語法(譯者注:現在在JSP中也可以不用#而訪問默認的ValueStack). 這是一個很好的便利特性, 但是小心, 它有時也會把你陷進去. <@ww.url id="url" value="http://www.yahoo.com"/>
Click <a xhref="${url}">here</a>!
Webwork-FreeMarker整合提供的內建變量如下:
Name Description
stack 值棧本身, 方便使用 ${stack.findString('ognl expr')}的方式調用
action 最近執行的action
response HttpServletResponse
res 與response相同
request HttpServletRequest
req 與reqeust相同
session HttpSession
application ServletContext
base request的上下文路徑(context path)
標簽支持
FreeMarker是很棒的模版語言, 因為它完整的支持標簽(tag). 參照WebWork提供的 FreeMarker Tags 文檔中的如何使用通用(generic) Tags 部分獲取更多信息. 除了那些, 你還可以使用任何的JSP標簽(tag), 就像這樣:
<#assign mytag=JspTaglibs["/WEB-INF/mytag.tld"]>
<@mytag.tagx attribute1="some ${value}"/>
這里 mytag.tld 是你使用的JSP標簽庫的定義文件. 注意: 為了使用FreeMarker的這個支持, 你必須開啟 web.xml 2.1.x compatibility 文檔中的 JSPSupportServlet.
提示和技巧
下面是在使用FreeMarker構建WebWork應用程序時的一些有用的進階功能.
類型轉換與本地化
FreeMarker內置支持日期與數字的格式化. 格式化的規則基于action request的地區信息(locale), locale是通過webwork.properties配置的, 它也可以通過I18n Interceptor進行覆蓋. 這種方式一般會完美的滿足你的需求, 但是你要記住, 這些格式化信息是通過FreeMarker處理的,而不是通過WebWork的類型轉換支持實現.
如果你希望WebWork根據你所指定的類型轉換處理格式化, 你不應該使用平常的&{...}語法. 取而代之, 你應該使用property標簽. 區別在于property標簽特別為OGNL表達式設計, 計算它的值, 然后將結果用你指定的Type Conversion轉換為String. 平常使用的${...}語法則會使用FreeMarker的表達式語言(EL), 計算它的值, 然后通過內建的格式化規則轉化為String. 這些區別甚微, 但是一定要了解.
擴展
有時你可能需要擴展WebWork提供的FreeMarker支持. 最常見的原因是你希望引入你自己的標簽, 就像你擴展WebWork內建標簽一樣.
如果需擴展, 首先要新建一個繼承 com.opensymphony.webwork.views.freemarker.FreemarkerManager 并且重載了相應方法的類. 然后將下面代碼添加到webwork.properties:
webwork.freemarker.manager.classname = com.yourcompany.YourFreeMarkerManager
ObjectWrapper設置
如果你熟悉了FreeMarker, 你會發現它的敏感性會帶來一些困擾. 最常見的方法就是嘗試使用FreeMarker提供的BeanWrapper. 如果你不知道那是什么,別擔心. 只要知道這些酒可以了:
WebWorkBeanWrapper繼承自默認的FreeMarker BeansWrapper, 提供了基本完全一致的功能, 只是修改了maps處理機制. 一般, FreeMarker有兩種操作模式: 一種支持友好的內置的map (?key, ?values, etc),但是只支持String作為key; 或者特殊的內置支持(例如: ?key 返回map的相應方法而不是key), 但是它支持String和String相似的非String作為key. WebWork提供了兩種情況下的可選的實現方案.
這種特殊的做法也許會讓你迷惑或產生問題. 所以, 你可以將 webwork.properties 中的*webwork.freemarker.wrapper.altMap*設置為false, 允許替換為常規的BeansWrapper邏輯.
語法注釋
如果是FreeMarker 2.3.4, 還支持另外的語法. 這種可選的語法在你感覺你使用的IDE(尤其是ItelliJ IDEA)在默認的語法下運行困難時非常有用. 關于這種語法的更多內容, 請閱讀這里