網頁靜態化解決方案在實際開發中運用比較多,例如新聞網站,門戶網站中的新聞頻道或者是文章類的頻道。html
對於電商網站的商品詳細頁來講,至少幾百萬個商品,每一個商品又有大量的信息,這樣的狀況一樣也適用於使用網頁靜態化來解決。web
網頁靜態化技術和緩存技術的共同點都是爲了減輕數據庫的訪問壓力,可是具體的應用場景不一樣,緩存比較適合小規模的數據,而網頁靜態化比較適合大規模且相對變化不太頻繁的數據。另外網頁靜態化還有利於SEO。數據庫
另外咱們若是將網頁以純靜態化的形式展示,就可使用Nginx這樣的高性能的web服務器來部署。Nginx能夠承載5萬的併發,而Tomcat只有幾百。關於Nginx咱們在後續的課程中會詳細講解。json
今天咱們就研究網頁靜態化技術----Freemarker 。緩存
FreeMarker 是一個用 Java 語言編寫的模板引擎,它基於模板來生成文本輸出。FreeMarker與 Web 容器無關,即在 Web 運行時,它並不知道 Servlet 或 HTTP。它不只能夠用做表現層的實現技術,並且還能夠用於生成 XML,JSP 或 Java 等。服務器
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
模板文件中四種元素併發
1、文本,直接輸出的部分
2、註釋,即<#--...-->格式不會輸出
3、插值(Interpolation):即${..}部分,將使用數據模型中的部分替代輸出
4、FTL指令:FreeMarker指令,和HTML標記相似,名字前加#予以區分,不會輸出。ide
咱們如今就建立一個簡單的建立模板文件test.ftl函數
<html> <head> <meta charset="utf-8"> <title>Freemarker入門小DEMO </title> </head> <body> <#--我只是一個註釋,我不會有任何輸出 --> ${name},你好。${message}<br> <#assign age="18"> 年齡:${age}<br> <#assign info={"sex":"男","hobbys":"唱跳rap"}> 性別:${info.sex}<br> 愛好:${info.hobbys} <#include "head.ftl"> <ul> 無序列表的個數:${grandList?size} <#list grandList as entity> <li> ${entity} </li> </#list> </ul> <h3>map集合取數據</h3> 姓名:${person.name} 年齡:${person.age}<br> <h3>時間類型:</h3> 當前日期:${date?date}<br> 當前時間:${date?time}<br> 時間戳:${date?datetime}<br> 時間格式化:${date?string("yyyy/MM/dd HH:mm:ss")} <h3>身份證號</h3> 以字符串形式輸出:${id?c} <h3>??判斷變量是否存在</h3> <#if aaa??> aaa存在 <#else > aaa不存在 </#if> <h3>判斷變量是否存在,不存在時!賦默認值</h3> <#if aaa??> aaa存在 ${aaa} <#else > aaa不存在 ${aaa!'111'} </#if> </body> </html>
使用步驟:性能
第一步:建立一個 Configuration 對象,直接 new 一個對象。構造方法的參數就是 freemarker的版本號。
第二步:設置模板文件所在的路徑。
第三步:設置模板文件使用的字符集。通常就是 utf-8.
第四步:加載一個模板,建立一個模板對象。
第五步:建立一個模板使用的數據集,能夠是 pojo 也能夠是 map。通常是 Map。
第六步:建立一個 Writer 對象,通常建立一 FileWriter 對象,指定生成的文件名。
第七步:調用模板對象的 process 方法輸出文件。
第八步:關閉流
代碼:
public class FreeMarkerTest { @Test public void test01() throws IOException, TemplateException { //1.建立配置類 Configuration configuration = new Configuration(Configuration.getVersion()); //2.設置模板所在的目錄 configuration.setDirectoryForTemplateLoading(new File("D:\\wrokspace\\ideaspace\\freemarker_demo01\\src\\main\\resources\\ftl")); //3.設置字符集 configuration.setDefaultEncoding("utf-8"); //4.加載模板 Template template = configuration.getTemplate("test.ftl"); //5.建立數據模型 Map map = new HashMap(); map.put("name", "luli"); map.put("message", "歡迎來到王者榮耀"); //list類型 List list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); map.put("grandList", list); //map類型 HashMap map1 = new HashMap(); map1.put("name", "曜"); map1.put("age", "20"); map.put("person", map1); //date類型 map.put("date", new Date()); //number類型處理 map.put("id", 41038111112412L);//6.建立輸出流 FileWriter fw = new FileWriter("E:\\test.html"); //7.輸出 template.process(map, fw); //8.關流 if(fw != null){ fw.close(); } } }
<html> <head> <meta charset="utf-8"> <title>Freemarker入門小DEMO </title> </head> <body> luli,你好。歡迎來到王者榮耀<br> 年齡:18<br> 性別:男<br> 愛好:唱跳rap <h1>include包含頁面</h1><ul> 無序列表的個數:4 <li> a </li> <li> b </li> <li> c </li> <li> d </li> </ul> <h3>map集合取數據</h3> 姓名:曜 年齡:20<br> <h3>時間類型:</h3> 當前日期:2019-11-26<br> 當前時間:11:13:56<br> 時間戳:2019-11-26 11:13:56<br> 時間格式化:2019/11/26 11:13:56 <h3>身份證號</h3> 以字符串形式輸出:41038111112412 <h3>??判斷變量是否存在</h3> aaa不存在 <h3>判斷變量是否存在,不存在時!賦默認值</h3> aaa存在 41,038,111,112,412 </body> </html>
此指令用於在ftl模版頁面上定義一個變量
(1)定義簡單類型:
<#assign linkman="周先生"> 聯繫人:${linkman} |
(2)定義對象類型:
<#assign info={"mobile":"13301231212",'address':'北京市昌平區王府街'} > 電話:${info.mobile} 地址:${info.address} |
運行效果:
此指令用於模板文件的嵌套
建立模板文件head.ftl
<h1>信息網</h1> |
咱們修改test.ftl,在模板文件中使用include指令引入剛纔咱們創建的模板
<#include "head.ftl"> |
在模板文件上添加
<#if success=true> 你已經過實名認證 <#else> 你未經過實名認證 </#if> |
在代碼中對str變量賦值
map.put("success", true); |
在freemarker的判斷中,可使用= 也可使用==
需求,實現商品價格表,以下圖:
(1)代碼中對變量goodsList賦值
(2)在模板文件上添加
----商品價格表----<br> <#list goodsList as goods> ${goods_index+1} 商品名稱: ${goods.name} 價格:${goods.price}<br> </#list> |
若是想在循環中獲得索引,使用 循環變量+_index 就能夠獲得。
內建函數語法格式: 變量+?+函數名稱
咱們一般要獲得某個集合的大小,以下圖:
咱們使用size函數來實現,代碼以下:
共 ${goodsList?size} 條記錄 |
咱們一般須要將json字符串轉換爲對象,那如何處理呢?看代碼
<#assign text="{'bank':'工商銀行','account':'10101920201920212'}" /> <#assign data=text?eval /> 開戶行:${data.bank} 帳號:${data.account} |
代碼中對變量賦值:
map.put("today", new Date()); |
在模板文件中加入
當前日期:${today?date} <br> 當前時間:${today?time} <br> 當前日期+時間:${today?datetime} <br> 日期格式化: ${today?string("yyyy年MM月")} |
運行效果以下:
代碼中對變量賦值:
map.put("point", 102920122); |
修改模板:
累計積分:${point} |
頁面顯示:
咱們會發現數字會以每三位一個分隔符顯示,有些時候咱們不須要這個分隔符,就須要將數字轉換爲字符串,使用內建函數c
累計積分:${point?c} |
頁面顯示效果以下:
9
若是你在模板中使用了變量可是在代碼中沒有對變量賦值,那麼運行生成時會拋出異常。可是有些時候,有的變量確實是null,怎麼解決這個問題呢?
用法爲:variable??,若是該變量存在,返回true,不然返回false
<#if aaa??> aaa變量存在 <#else> aaa變量不存在 </#if> |
咱們除了能夠判斷是否爲空值,也可使用!對null值作轉換處理
在模板文件中加入
${aaa!'-'} |
在代碼中不對aaa賦值,也不會報錯了 ,當aaa爲null則返回!後邊的內容-
FreeMarker表達式中徹底支持算術運算,FreeMarker支持的算術運算符包括:+, - , * , / , %
邏輯運算符有以下幾個:
邏輯與:&&
邏輯或:||
邏輯非:!
邏輯運算符只能做用於布爾值,不然將產生錯誤
表達式中支持的比較運算符有以下幾個:
1 = 或者 ==: 判斷兩個值是否相等.
2 !=: 判斷兩個值是否不等.
3 >或者gt:判斷左邊值是否大於右邊值
4 >=或者gte:判斷左邊值是否大於等於右邊值
5 <或者lt:判斷左邊值是否小於右邊值
6 <=或者lte:判斷左邊值是否小於等於右邊值
注意: =和!=能夠用於字符串,數值和日期來比較是否相等,但=和!=兩邊必須是相同類型的值,不然會產生錯誤,並且FreeMarker是精確比較,"x","x ","X"是不等的.其它的運行符能夠做用於數字和日期,但不能做用於字符串,大部分的時候,使用gt等字母運算符代替>會有更好的效果,由於 FreeMarker會把>解釋成FTL標籤的結束字符,固然,也可使用括號來避免這種狀況,如:<#if (x>y)>