什麼是 FreeMarker?
FreeMarker 是一款模板引擎:即基於模板和資料來源生成輸出文字(html網頁,配置檔案,電子郵件,原始碼)的通用工具。它是一個 java 類庫,最初被設計用來在MVC模式的Web開發框架中生成HTML頁面,它沒有被繫結到Servlet或HTML或任意Web相關的東西上。也可以用於非Web應用環境中。
模板編寫使用FreeMarker Template Language(FTL)。使用方式類似JSP的EL表示式。模板中專注於如何展示資料,模板之外可以專注於要展示什麼資料。
為什麼用 FreeMarker?
-
FreeMarker 基於資料模型和模板來渲染,將業務邏輯和表現層分離。 JSP開發中,頁面會有大量業務邏輯,不利於維護和閱讀,使用FreeMarker可以避免這一問題。
-
**有利於分工合作。**HTML設計師可以關注頁面的設計無需面對頁面的業務邏輯,同時修改頁面程式碼也不需要程式設計師編重新譯程式碼。
-
**提高開發效率。**相對於JSP,FreeMarker不需要每次修改後重新編譯,因此在開發除錯中可以有效節省時間。
-
**有利於提高訪問速度。**對於不會頻繁發生變化的頁面,建議使用FreeMarker生成的靜態頁面。而不是每次都要動態生成的JSP頁面。
-
**可以提高併發量。**例如單臺tomcat容器只支援幾百併發,如果將靜態頁面放到效能更好的nginx伺服器上,可以支援幾萬的併發。
-
靜態頁面對SEO更友好。
-
**不佔用JVM的PermGen space。**因為不會被編譯成類,所以不會佔用web伺服器永生代的空間,避免OutOfMemoryError:PermGen space的問題。
怎麼用 FreeMarker?
在java中使用
@Test
public void testFreeMarker() throws Exception {
// 把freemarker的jar包新增到工程中
//建立一個Configuration物件
Configuration configuration = new Configuration(Configuration.getVersion());
// 告訴config物件模板檔案存放的路徑。
configuration.setDirectoryForTemplateLoading(new File("ftl directory absolute path"));
// 設定config的預設字符集。一般是utf-8
configuration.setDefaultEncoding("utf-8");
//從config物件中獲得模板物件。需要制定一個模板檔案的名字。
Template template = configuration.getTemplate("test.ftl");
//建立模板需要的資料集。可以是一個map物件也可以是一個pojo,把模板需要的資料都放入資料集。
Map root = new HashMap<>();
root.put("hello", "hello freemarker");
//建立一個Writer物件,指定生成的檔案儲存的路徑及檔名。
Writer out = new FileWriter(new File("out html file absolute path"));
//呼叫模板物件的process方法生成靜態檔案。需要兩個引數資料集和writer物件。
template.process(root, out);
//關閉writer物件。
out.flush();
out.close();
}
複製程式碼
模板載入器
當然也可以不指定絕對路徑,使用模板載入器,FreeMarker提供了模板載入器可以直接從資料來源載入模板。
-
ClassTemplateLoader:從classpath中載入模板。
-
FileTemplateLoader:在檔案系統中從指定資料夾載入模板。
-
StringTemplateLoader:從一個字串 Map 中載入模板。
-
URLTemplateLoader:從 URL 中載入模板。 你必須要實現 getURL 方法。
-
WebappTemplateLoader:從 servlet 上下文中載入模板。
使用方式:
Configuration configuration = new Configuration();
configuration.setTemplateLoader(
new WebappTemplateLoader(servletContext, "WEB-INF/content"));
複製程式碼
在專案中使用
在專案中使用的話,可以直接託管給框架即可。
新增依賴
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
複製程式碼
配置spring
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
複製程式碼
然後使用時從FreeMarkerConfigurer拿到Configuration物件:
Configuration configuration = freeMarkerConfigurer.getConfiguration();
複製程式碼
FreeMarker 基本語法
簡單型別
使用類似EL表示式。
${hello}
複製程式碼
包裝型別
<html>
<head>
<title>${title}</title>
</head>
<body>
<label>學號:</label>${student.id}<br>
<label>姓名:</label>${student.name}<br>
</body>
</html>
複製程式碼
遍歷集合/陣列
<#list people as p>
${p.id}/${p.name}
</#list>
複製程式碼
獲取當前迭代索引
<#list people as p
${p_index}
</#list>
複製程式碼
新增判斷條件
<#if 條件>
<#else>
</#if>
複製程式碼
日期型別
#預設格式
1:date
${cur_time?date}
2:datetime
${cur_time?datetime}
3:time
${cur_time?time}
#自定義格式
${cur_time?string("yyyy-MM-dd HH:mm:ss")}
複製程式碼
處理 null 值
map.put("val",null)
val值為:${val!}
複製程式碼
當val為空時,顯示為空字串,即
val值為:
複製程式碼
也可以指定值為空時的預設值。
${val!"預設值"}
複製程式碼
也可以使用條件語句做非空判斷。
<#if curdate ??>
當前日期:${curdate?string("yyyy/MM/dd HH:mm:ss")}
<#else>
curdate屬性為null
</#if>
複製程式碼
include
可以引入其他模板片段。
<#include "/include/head.ftl">
複製程式碼
json 支援
?eval
可以將字串轉為json物件,然後在模板中當包裝型別使用。
<#assign user = userString?eval>
User:${user.name}
複製程式碼
共享變數
可以設定自動新增到所有模板的資料,這樣就可以在所有模板中使用。
configuration.setSharedVariable("share_value_key", "share_value");
複製程式碼
補充
-
需要使用FreeMarker的頁面在資料庫更新時要及時更新,否則使用者訪問到的會是過期的頁面。
-
FreeMarker資料模型的map的key只可以是String型別。