網頁靜態化解決方案Freemarker(一)
序言:
沉澱了三個月,逐步將自己最近兩年在公司中用到的技術和知識點,重新整理歸納了下,對比以前可以發現,現在技術更新越來越快,也越來越成熟,在網際網路企業,用到的技術也更先進,更領先,比如微服務、分散式和高併發等等。接下來我會將自己創業的時候在客戶做專案,用到的一些技術和知識點給大家分享,供大家參考學習。下面我們先從網頁靜態化技術開始,這在專案中還是用的比較多的,如果小夥伴還有什麼希望瞭解的技術,可以在留言區註釋,我會挑選自己擅長的地方給大家分享。下面開始今天的學習吧!
——WZY
一、什麼是Freemarker?它是幹什麼用的?為什麼要使用網頁靜態化技術?
1.什麼是Freemarker:
FreeMarker 是一個用 Java 語言編寫的模板引擎,它基於模板來生成文字輸出。FreeMarker 與 Web 容器無關,即在 Web 執行時,它並不知道 Servlet 或 HTTP。它不僅可以用作表現層的實現技術,而且還可以用於生成 XML, JSP 或 Java 等。
##這是什麼意思呢?有的同學可能讀完,也沒明白說的是啥。還記得之前,我給大家分享的mybatis的逆向工程嗎?其實原理類似Freemarker。簡單來說,就是可以通過編碼java程式碼,將固定模板和動態的引數填充到一起,生成所需要的檔案。根據不同的模板,可以生成不同的檔案,比如提供HTML模板,可以生成所需要的HTML檔案。
2.為什麼要使用Freemarker?他的使用場景是什麼?
網頁靜態化解決方案在實際開發中運用比較多,例如新聞網站,入口網站中的新聞頻道或者是文章類的頻道。也比如說一些電商的商品詳情頁面,雖然每個商品的詳情內容是不一樣的,但是它整體的佈局是一致了,比如每個商品都有標題,價格,圖片,商品介紹等等,我們使用Freemarker將固定不變的內容定義層模板,然後將不動態的內容去從資料庫中查詢出來,再繫結到模板一個一個對應位置,就可以生成,每個商品自己的詳情頁了。
那麼我們為什麼要使用網頁靜態化呢,像我們以前那樣,直接定義好頁面,使用者訪問的時候,再將頁面的動態內容查詢填充展示不行嗎?很顯然,使用了網頁靜態化技術,使用者訪問的是生成好的靜態頁面,不用再直接去資料庫中取查詢資料。網頁靜態化技術和快取技術的共同點都是為了減輕資料庫的訪問壓力,但是具體的應用場景不同,快取比較適合小規模的資料,而網頁靜態化比較適合大規模且相對變化不太頻繁的資料。
另外網頁靜態化還有利於 SEO。 另外我們如果將網頁以純靜態化的形式展現,就可以使用 Nginx 這樣的高效能的 web伺服器來部署。 Nginx 可以承載 5 萬的併發,而 Tomcat 只有幾百。關於 Nginx 我在後續的部落格中會詳細講解。
二、瞭解了Freemarker的基本概念 ,下面我們通過一個小案例,來具體瞭解下Freemarker。
1.使用Freemarker需要現在建立maven工程,引入依賴,還不知道如何使用maven工程的小夥伴,可以看看我之前的部落格關於maven的詳細介紹。
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
2.建立模板檔案,這裡我們以生成html檔案為例(通俗來說模板就是用於生產的模具)。
先了解下模板檔案中常用的四種元素:
1)、文字,直接輸出的部分
2)、註釋,即<#--...-->格式不會輸出
3)、插值(Interpolation):即${..}部分,將使用資料模型中的部分替代輸出 。
4)、 FTL 指令: FreeMarker 指令,和 HTML 標記類似,名字前加#予以區分,不會輸出。
我們現在就建立一個簡單的建立模板檔案 test.ftl (這個字尾不是非要寫出ftl,但是一般都這樣寫)
<html> <head> <meta charset="utf-8"> <title>Freemarker測試</title> </head> <body> <#--我只是一個註釋,我不會有任何輸出 --> 跟html中的註釋<-- -->是所有區別的,html中註釋雖然不會再頁面顯示,但是還是會顯示在原始碼中,而#<-- --> 僅從程式設計師看的,不會顯示在生成的原始碼中。 ${name},你好。 ${message} ${...} 這就是插值,相當於佔位置,等待資料填充。很類似以前學習的JSP頁面中的{}從域中取值 </body> 其他地方就是文字,會直接輸出到生成的原始碼中。 </html>
3.程式設計程式碼,填充模板,生成說需要的原始碼檔案
使用步驟:
第一步:建立一個 Configuration 物件,直接 new 一個物件。構造方法的引數就是freemarker 的版本號。
第二步:設定模板檔案所在的路徑。
第三步:設定模板檔案使用的字符集。一般就是 utf-8.
第四步:載入一個模板,建立一個模板物件。
第五步:建立一個模板使用的資料集,可以是 pojo 也可以是 map。一般是 Map。
第六步:建立一個 Writer 物件,一般建立一 FileWriter 物件,指定生成的檔名。
第七步:呼叫模板物件的 process 方法輸出檔案。
第八步:關閉流
//1.建立配置類,這個configuration是freemarker提供的,不要導錯包了 Configuration configuration=new Configuration(Configuration.getVersion()); //2.設定模板所在的目錄,這裡定義的就是剛剛test.ftl所存放的真實目錄 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,注意的是key需要跟插值中的對應上 Map map=new HashMap(); map.put("name", "張三 "); map.put("message", "歡迎來到Freemarker! "); //6.建立 Writer 物件,代表生成的原始碼會存放到哪裡 Writer out =new FileWriter(new File("d:\\test.html")); //7.輸出 template.process(map, out); //8.關閉 Writer 物件,切記不要忘記關流,不然以上的資料都還是在記憶體中,需要refresh才可以持久化到磁碟,這是IO流的知識點. out.close();
4.這時候,D盤下就生成了一個test.html的檔案了,開啟看看!看到這個頁面,恭喜你,成功了!
5.讓我們來看看生成的原始碼是啥樣的
<html> <head> <meta charset="utf-8"> <title>freemarker測試</title> </head> <body> 張三,你好。歡迎來到Freemarker! </body> </html>
對比模板,可以看到如我們定義的一樣。文字原樣輸出,註釋不再原始碼,插值被填充。
三、接下來我們讓我們學習FTL指令。
1.assign指令:此指令用於在頁面上定義一個變數
1)可以直接一個簡單型別,等同於給一個變數賦值
2)也可以定義個物件型別,取值的時候,根據物件名.屬性名,跟JS中一樣
(1)定義簡單型別: <#assign linkman="張三"> 聯絡人: ${linkman} (2)定義物件型別: <#assign info={"mobile":"1314520",'address':'中國臺灣省'} > 電話: ${info.mobile} 地址: ${info.address}
頁面效果:
2.include指令
此指令用於指定模板的巢狀,類似JSP頁面中引入其他JSP檔案,一個道理。
建立模板檔案 head.ftl <h1>測試官網</h1> 我們修改 test.ftl,在模板檔案中使用 include 指令引入剛才我們建立的模板 <#include "head.ftl">
3.if 指令
在模板檔案上新增 <#if success=true> 你已通過實名認證 <#else> 你未通過實名認證 </#if>
在java程式碼中對succsee變數賦值 map.put("success", true); 在 freemarker 的判斷中,可以使用= 也可以使用==
頁面效果:
4.list 指令
在後臺java程式碼中,建立一個集合
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);
在模板檔案中新增:
----商品價格表----<br> <#list goodsList as goods> ${goods_index} 商品名稱: ${goods.name} 價格: ${goods.price}<br> </#list>
頁面效果:
5. 內建函式
語法格式:變數+?+函式名稱
5.1 獲得集合大小:比如要獲得上面goodsLIst集合的長度可以這樣寫
一共 ${goodsList?size} 條記錄
頁面效果:
5.2 轉換JSON字串物件
我們通常需要將 json 字串轉換為物件,那如何處理呢?看程式碼
<#assign text="{'bank':'工商銀行','account':'10101920201920212'}" /> <#-- 這裡定義的是一個json字串{}是被""包裹在 --> <#assign data=text?eval /> <#-- 通過?eval將json字串text轉換成物件,賦值給變數data,就可以通過data取值了 --> 開戶行: ${data.bank} 賬號: ${data.account}
5.3 日期格式化
程式碼中對變數賦值:map.put("taday",new Date()),然後在頁面取:
當前日期: ${today?date} <br> 當前時間: ${today?time} <br> 當前日期+時間: ${today?datetime} <br> 日期格式化: ${today?string("yyyy 年 MM 月")}
頁面效果:
5.4 數字轉換為字串
程式碼中對變數賦值 map.put("number",10231231);
那麼用${number}取值 頁面會是 102,31,231 的這種格式
使用 ${number?c} 會原樣輸出:10231231
5.5 空值處理運算子
如果你在模板中使用了變數但是在程式碼中沒有對變數賦值,那麼執行生成時會丟擲異常。但是有些時候,有的變數確實是 null,怎麼解決這個問題呢?
用法一: 用法為:variable??,如果該變數存在,返回 true,否則返回 false <#if aaa??> aaa 變數存在 <#else> aaa 變數不存在 </#if>
用法二: 我們除了可以判斷是否為空值,也可以使用!對 null 值做轉換處理 在模板檔案中加入 ${aaa!'-'} 在程式碼中不對 aaa 賦值,也不會報錯了 ,當 aaa 為 null 則返回!後邊的內容-
5.6 運算子
1)算數運算子
FreeMarker 表示式中完全支援算術運算,FreeMarker 支援的算術運算子包括:+, - , * , / , %
邏輯運算子
2)邏輯運算子有如下幾個:
邏輯與:&&
邏輯或:||
邏輯非:!
邏輯運算子只能作用於布林值,否則將產生錯誤
3)比較運算子
表示式中支援的比較運算子有如下幾個:
1 =或者==:判斷兩個值是否相等.
2 !=:判斷兩個值是否不等.
3 >或者 gt:判斷左邊值是否大於右邊值
4 >=或者 gte:判斷左邊值是否大於等於右邊值
5 <或者 lt:判斷左邊值是否小於右邊值
6 <=或者 lte:判斷左邊值是否小於等於右邊值
注意: =和!=可以用於字串,數值和日期來比較是否相等,但=和!=兩邊必須是相同型別的值,否則會產生錯誤,而且 FreeMarker 是精確比較,"x","x ","X"是不等的.其它的執行符可以作用於數字和日期,但不能作用於字串,大部分的時候,使用 gt等字母運算子代替>會有更好的效果,因為 FreeMarker 會把>解釋成 FTL 標籤的結束字元,當然,也可以使用括號來避免這種情況,如:<#if (x>y)>
結尾:今天Freemarker的基本入門就介紹到這裡了,下一期,我們通過實戰來,深入瞭解具體在專案中如何使用Freemarker!
<