@(編程)
1. 簡介
FreeMarker是一個模板引擎,一個基於模板生成文本輸出的通用工具,使用純Java編寫。它是為Java程序員提供的一個開發包。它不是面向最終用戶的,而是為程序員提供的一款可以嵌入他們所開發產品的應用程序。
FreeMarker被設計用來生成HTML Web頁面,特別是基於MVC模式的應用程序。
雖然FreeMarker具有一些編程的能力,但通常由Java程序准備要顯示的數據,由FreeMarker生成頁面,通過模板顯示准備的數據。
FreeMarker不是一個Web應用框架,而適合作為Web應用框架一個組件
FreeMarker與容器無關,因為它並不知道HTTP或Servlet;FreeMarker同樣可以應用於非Web應用程序環境。
FreeMarker更適合作為Model2框架(如Struts)的視圖組件,你也可以在模板中使用JSP標記庫
FreeMarker是免費的
而且你還可以通過Eclipse的插件來編輯FreeMarker,經過驗證,FreeMarker 最好的 Eclipse 編輯插件是 JBoss Tools。
2. FreeMarker特性
2.1. 通用目標
能夠生成各種文本:HTML、XML、RTF、Java源代碼等等
易於嵌入到你的產品中:輕量級;不需要Servlet環境
插件式模板載入器:可以從任何源載入模板,如本地文件、數據庫等等
你可以按你所需生成文本:保存到本地文件;作為Email發送;從Web應用程序發送它返回給Web瀏覽器
2.2. 強大的模板語言
所有常用的指令:include、if/elseif/else、循環結構
在模板中創建和改變變量
幾乎在任何地方都可以使用復雜表達式來指定值
命名的宏,可以具有位置參數和嵌套內容
名字空間有助於建立和維護可重用的宏庫,或者將一個大工程分成模塊,而不必擔心名字沖突
輸出轉換塊:在嵌套模板片段生成輸出時,轉換HTML轉義、壓縮、語法高亮等等;你可以定義自己的轉換
2.3. 通用數據模型
FreeMarker不是直接反射到Java對象,Java對象通過插件式對象封裝,以變量方式在模板中顯示
你可以使用抽象(接口)方式表示對象(JavaBean、XML文檔、SQL查詢結果集等等),告訴模板開發者使用方法,使其不受技術細節的打擾
2.4. 為Web准備
在模板語言中內建處理典型Web相關任務(如HTML轉義)的結構
能夠集成到Model2 Web應用框架中作為JSP的替代
支持JSP標記庫
為MVC模式設計:分離可視化設計和應用程序邏輯;分離頁面設計員和程序員
2.5. 智能的國際化和本地化
字符集智能化(內部使用UNICODE)
數字格式本地化敏感
日期和時間格式本地化敏感
非US字符集可以用作標識(如變量名)
多種不同語言的相同模板
2.6. 強大的XML處理能力
<#recurse> 和<#visit>指令(2.3版本)用於遞歸遍歷XML樹
在模板中清楚和直覺的訪問XML對象模型
開源論壇 JForum 就是使用了 FreeMarker 做為頁面模板。
3. 優勢與不足
3.1. 優勢
可以徹底的分離表現層和業務邏輯
使用JSP開發過程中,在頁面中大量的存在業務邏輯代碼,使得頁面的內容非常混亂,在后期大量的修改維護過程中就變得非常的困難。
FreeMarker不支持Java腳本代碼,FreeMarker的原理是,模板+數據模型=輸出。模板只負責數據在頁面中的表現,不涉及任何的邏輯代碼,而所有的邏輯都是由數據模型來處理的。用戶最終看到的輸出是模板和數據模型合並后創建的。
可以提高開發效率
在以往的開發中,使用的都是JSP頁面來展示數據的,即所謂的表現層。我們都知道,JSP在第一次執行的時候需要轉換成Servlet類,開發階段進行功能調試時,需要頻繁的修改JSP,每次修改都要編譯和轉換,那么試想一下,一天中我們浪費在程序編譯的時間有多少。
相對於JSP來說,FreeMarker模板技術不存在編譯和轉換的問題,所以就不會存在上述問題。而且開發過程中,我們再不必等待界面設計開發人員完成頁面原型后,我們再來開發程序。
而且,一些特定的系統,比如OA工作流系統中,就需要動態生成表單技術,這就為其提供了很好的實現依據。使得在整個流程的進行中,生成不同的表單就簡單了很多。
使得開發過程中的人員分工更加明確
以往用JSP顯示數據時,一些程序員並不熟悉界面設計技術,反之界面開發人員,也並不熟悉程序語言。對兩者而言,交替性的工作本身就有難度。有時候稍有不慎,可能會將整個頁面元素刪除或去掉了某個程序符號,使得頁面走樣或程序錯誤,這樣就需要雙方相互溝通協作,解決出現的問題。有時候因為項目中的時間、任務量等因素的存在,可能這個工作就由一個人來完成,這樣就可能加大某一方開發人員的工作量。
使用FreeMarker后,作為界面開發人員,只專心創建HTML文件、圖像以及Web頁面的其他可視化方面,不用理會數據;而程序開發人員則專注於系統實現,負責為頁面准備要顯示的數據。
3.2. 不足
在修改模板后,可能會看到已經過期的數據
使用FreeMarker模板技術,生成靜態的HTML頁面后,如果一旦模板改變,而沒有及時更新模板生成的HTML頁面的話,用戶看到的就是過期的數據。
FreeMarker的變量必須有值
FreeMarker模板技術在應用過程中,FreeMarker中的變量必須要賦值,如果不賦值,那么就會拋出異常。FreeMarker沒有一個默認的null處理,甚至也不接受一個null值。想避免錯誤就要應用if/elseif/else 指令進行判段,如果對每一個變量都判斷的話,那么則反而增加了編程的麻煩。
FreeMarker的Map限定Key必須是String,其他數據類型無法操作
Map問題,即FreeMarker中不能支持非String的Key值,這樣在進行一些復雜迭代時就需要作一些其他的轉換,如將一個Map拆分為兩個或多個Map。
FreeMarker不支持集群應用
為了編成的方便性,把序列化的東西都放到了Session中,如Session,request等,在開發的過程中確實方便,但如果將應用放到集群中,就會出現錯誤。
4. 代碼示例
4.1. java代碼
package com.demo.index;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
public class TestFreeMarker {
public static void main(String[] args) {
String dir = "D:/Downloads/jfinal-2.2_demo/jfinal_demo/res";
Configuration cfg = new Configuration();
try {
cfg.setDirectoryForTemplateLoading(new File(dir));
cfg.setObjectWrapper(new DefaultObjectWrapper());
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
Map root = new HashMap();
root.put("name", "hello,keke");
Template template = cfg.getTemplate("test.ftl");
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(dir + "/out.txt")));
try {
template.process(root, out);
} catch (TemplateException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2. 模板代碼
<span style="font-family:Microsoft YaHei;">我的測試程序:${name}</span>
4.3. 輸出
<span style="font-family:Microsoft YaHei;">我的測試程序:hello,keke</span>