本文介紹了freemarker的內建、FTL指令、内建函數、運算符等常用操作。
1、為什麼要使用網頁靜态化技術
網頁靜态化解決方案在實際開發中運用比較多,例如新聞網站,門戶網站中的新聞頻道或者是文章類的頻道。

對于電商網站的商品詳細頁來說,至少幾百萬個商品,每個商品又有大量的資訊,這樣的情況同樣也适用于使用網頁靜态化來解決。
網頁靜态化技術和緩存技術的共同點都是為了減輕資料庫的通路壓力,但是具體的應用場景不同,緩存比較适合小規模的資料,而網頁靜态化比較适合大規模且相對變化不太頻繁的資料。另外網頁靜态化還有利于SEO。
另外我們如果将網頁以純靜态化的形式展現,就可以使用Nginx這樣的高性能的web伺服器來部署。Nginx可以承載5萬的并發,而Tomcat隻有幾百。關于Nginx我們在後續的課程中會詳細講解。
今天我們就研究網頁靜态化技術----Freemarker 。
2、什麼是 Freemarker
FreeMarker 是一個用 Java 語言編寫的模闆引擎,它基于模闆來生成文本輸出。FreeMarker與 Web 容器無關,即在 Web 運作時,它并不知道 Servlet 或 HTTP。它不僅可以用作表現層的實作技術,而且還可以用于生成 XML,JSP 或 Java 等。
3、 Freemarker入門小DEMO
這裡介紹了freemarker的基本用法。
3.1 工程引入依賴
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
3.2 建立模闆檔案
模闆檔案中四種元素
1、文本,直接輸出的部分
2、注釋,即<#--...-->格式不會輸出
3、插值(Interpolation):即${..}部分,将使用資料模型中的部分替代輸出
4、FTL指令:FreeMarker指令,和HTML标記類似,名字前加#予以區分,不會輸出。
我們現在就建立一個簡單的建立模闆檔案test.ftl,這個最好在IDEA裡面編輯,否則會出現亂碼
<html>
<head>
<meta charset="utf-8">
<title>Freemarker入門小DEMO </title>
</head>
<body>
<#--我隻是一個注釋,我不會有任何輸出 -->
${name},你好。${message}
</body>
</html>
3.3生成檔案這裡有文本、插值和注釋
使用步驟:
第一步:建立一個 Configuration 對象,直接 new 一個對象。構造方法的參數就是 freemarker的版本号。
第二步:設定模闆檔案所在的路徑。
第三步:設定模闆檔案使用的字元集。一般就是 utf-8.
第四步:加載一個模闆,建立一個模闆對象。
第五步:建立一個模闆使用的資料集,可以是 pojo 也可以是 map。一般是 Map。
第六步:建立一個 Writer 對象,一般建立一 FileWriter 對象,指定生成的檔案名。
第七步:調用模闆對象的 process 方法輸出檔案。
第八步:關閉流
代碼:
建立Test類 main方法如下:
//1.建立配置類
Configuration configuration=new Configuration(Configuration.getVersion());
//2.設定模闆所在的目錄
configuration.setDirectoryForTemplateLoading(new File("D:/pinyougou_work/freemarkerDemo/src/main/resources/"));
//3.設定字元集
configuration.setDefaultEncoding("utf-8");
//4.加載模闆
Template template = configuration.getTemplate("test.ftl");
//5.建立資料模型
Map map=new HashMap();
map.put("name", "張三 ");
map.put("message", "歡迎來到神奇的品優購世界!");
//6.建立Writer對象
Writer out =new FileWriter(new File("d:\\test.html"));
//7.輸出
template.process(map, out);
//8.關閉Writer對象
out.close();
執行後,在D盤根目錄即可看到生成的test.html ,打開看看
4 、FTL指令
4.1 assign指令
此指令用于在頁面上定義一個變量
(1)定義簡單類型:
<#assign linkman="周先生">
聯系人:${linkman}
(2)定義對象類型:
<#assign info={"mobile":"13301231212",'address':'北京市昌平區王府街'} >
電話:${info.mobile} 位址:${info.address}
運作效果:
4.2 include指令
此指令用于模闆檔案的嵌套
建立模闆檔案head.ftl
<h1>黑馬資訊網</h1>
我們修改test.ftl,在模闆檔案中使用include指令引入剛才我們建立的模闆
<#include "head.ftl">
4.3 if指令
在模闆檔案上添加
<#if success=true>
你已認證實名認證
<#else>
你未通過實名認證
</#if>
在代碼中對str變量指派
map.put("success", true);
4.4 list指令在freemarker的判斷中,可以使用= 也可以使用==
需求,實作商品價格表,如下圖:
(1)代碼中對變量goodsList指派
List goodsList=new ArrayList();
Map goods1=new HashMap();
goods1.put("name", "蘋果");
goods1.put("price", 5.8);
Map goods2=new HashMap();
goods2.put("name", "香蕉");
goods2.put("price", 2.5);
Map goods3=new HashMap();
goods3.put("name", "橘子");
goods3.put("price", 3.2);
goodsList.add(goods1);
goodsList.add(goods2);
goodsList.add(goods3);
map.put("goodsList", goodsList);
(2)在模闆檔案上添加
----商品價格表----<br>
<#list goodsList as goods>
${goods_index+1} 商品名稱: ${goods.name} 價格:${goods.price}<br>
</#list>
如果想在循環中得到索引,使用循環變量+_index就可以得到。
5、 内建函數
内建函數文法格式: 變量+?+函數名稱
5.1 擷取集合大小
我們通常要得到某個集合的大小,如下圖:
我們使用size函數來實作,代碼如下:
共 ${goodsList?size} 條記錄
5.2 轉換JSON字元串為對象
我們通常需要将json字元串轉換為對象,那如何處理呢?看代碼
<#assign text="{'bank':'工商銀行','account':'10101920201920212'}" />
<#assign data=text?eval />
開戶行:${data.bank} 賬号:${data.account}
5.3 日期格式化
代碼中對變量指派:
dataModel.put("today", new Date());
在模闆檔案中加入
目前日期:${today?date} <br>
目前時間:${today?time} <br>
目前日期+時間:${today?datetime} <br>
日期格式化: ${today?string("yyyy年MM月")}
運作效果如下:
5.4 數字轉換為字元串
map.put("point", 102920122);
修改模闆:
累計積分:${point}
頁面顯示:
我們會發現數字會以每三位一個分隔符顯示,有些時候我們不需要這個分隔符,就需要将數字轉換為字元串,使用内建函數c
累計積分:${point?c}
頁面顯示效果如下:
6、空值處理運算符
如果你在模闆中使用了變量但是在代碼中沒有對變量指派,那麼運作生成時會抛出異常。但是有些時候,有的變量确實是null,怎麼解決這個問題呢?
6.1 判斷某變量是否存在:“??”
用法為:variable??,如果該變量存在,傳回true,否則傳回false
<#if aaa??>
aaa變量存在
<#else>
aaa變量不存在
</#if>
6.2 缺失變量預設值:“!”
我們除了可以判斷是否為空值,也可以使用!對null值做轉換處理
${aaa!'-'}
在代碼中不對aaa指派,也不會報錯了 ,當aaa為null則傳回!後邊的内容-
7、運算符
7.1 算數運算符
FreeMarker表達式中完全支援算術運算,FreeMarker支援的算術運算符包括:+, - , * , / , %
7.2 邏輯運算符
邏輯運算符有如下幾個:
邏輯與:&&
邏輯或:||
邏輯非:!
邏輯運算符隻能作用于布爾值,否則将産生錯誤
7.3 比較運算符
表達式中支援的比較運算符有如下幾個:
1 =或者==:判斷兩個值是否相等.
2 !=:判斷兩個值是否不等.
3 >或者gt:判斷左邊值是否大于右邊值
4 >=或者gte:判斷左邊值是否大于等于右邊值
5 <或者lt:判斷左邊值是否小于右邊值
6 <=或者lte:判斷左邊值是否小于等于右邊值
注意: =和!=可以用于字元串,數值和日期來比較是否相等,但=和!=兩邊必須是相同類型的值,否則會産生錯誤,而且FreeMarker是精确比較,"x","x ","X"是不等的.其它的運作符可以作用于數字和日期,但不能作用于字元串,大部分的時候,使用gt等字母運算符代替>會有更好的效果,因為 FreeMarker會把>解釋成FTL标簽的結束字元,當然,也可以使用括号來避免這種情況,如:<#if
(x>y)>