freemarker Java 模板引擎 基本语法
0?freemarker簡介
首先我們要先通過 官網:https://freemarker.apache.org/?了解什么是freemarker?以及他的使用方法。官方介紹如下:
Apache FreeMarker?是一個模板引擎:一個Java庫,用于根據模板和更改數據生成文本輸出(HTML網頁,電子郵件,配置文件,源代碼等)。模板是用FreeMarker模板語言(FTL)編寫的,這是一種簡單的專用語言(不像PHP這樣的完整編程語言)。通常,使用通用編程語言(如Java)來準備數據(發布數據庫查詢,進行業務計算)。然后,Apache FreeMarker使用模板顯示準備好的數據。在模板中,您將關注如何呈現數據,而在模板之外,您將關注于要呈現的數據。
這種方法通常被稱為MVC(模型視圖控制器)模式,并且特別受動態網頁的歡迎。它有助于將網頁設計者(HTML作者)與開發人員(通常是Java程序員)分開。設計人員不會在模板中面對復雜的邏輯,并且可以在程序員不必更改或重新編譯代碼的情況下更改頁面的外觀。
雖然FreeMarker最初是為在MVC Web應用程序框架中生成HTML頁面而創建的,但它并沒有綁定到servlet或HTML或任何與Web相關的內容。它也用于非Web應用程序環境。
通過點擊下圖紅色框文檔手冊 閱讀如何使用 freemarker
接下來開始介紹freemarker 基本用法。介紹之前先說明一下我們的開發環境
0.1 版本說明
IDEA :STS
JDK:1.8
freemarker Version:2.3.28
這里將通過maven項目進行說明我們的用法。首先引入freemarker 依賴到我們的maven項目中
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency>1 freemarker 用法之 Hello word
在resource目錄下創建template目錄并添加helloworld.ftl 模板文件 內容如下:
<html>??????????????? <head>??<title>hello world</title> </head>?<body>?<h1>this is ${who} hello World</h1></body>?? </html>??創建配置實例 并將模板和數據進行輸出
package cn.lijunkui.examples;import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.HashMap; import java.util.Map;import org.junit.Test;import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException;public class FreemarkerDemo {@Testpublic void helloWord() throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的來源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//這是模板的編碼cfg.setDefaultEncoding("UTF-8");//獲取模板Template template = cfg.getTemplate("helloworld.ftl"); //創建FreeMarker的數據模型 Map<String,String> root = new HashMap<String,String>(); root.put("who","freemarker");//這是輸出文件File file = new File("D://" +"helloWord.html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//將模板與數據模型合并template.process(root, out); out.flush(); out.close(); } }2 data-model:數據模型
hello word的示例其實就是?Template + data-model = output 接下來我們引用一下官方的示例介紹一下數據模型
數據模型是樹狀結構 如下圖
以上只是一個可視化;?數據模型不是文本格式,而是來自Java對象。對于Java程序員來說,root可能是帶有getUser()?和getLatestProduct()方法的Java對象,或者是Map帶有"user"和"latestProducts"鍵的Java?。同樣,?latestProduct也許是一個Java對象?getUrl()和getName()?方法。
<html> <head> <title>歡迎!</ title> </head> <body> <h1>歡迎${user}!</ h1> <p>我們的最新產品:<a href ="${latestProduct.url}"> ${latestProduct.name} </a>! </body> </html> @Testpublic void dataModel() throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的來源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//這是模板的編碼cfg.setDefaultEncoding("UTF-8");//獲取模板Template template = cfg.getTemplate("data-model.ftl"); //創建FreeMarker的數據模型 Map<String,Object> root = new HashMap<String,Object>(); root.put("user","Big Joe");Product product = new Product();product.setName("綠色鼠標");product.setUrl("products/greenmouse.html");root.put("latestProduct",product);//這是輸出文件File file = new File("D://" +"dataModel.html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//將模板與數據模型合并template.process(root, out); out.flush(); out.close(); }3 freemarker 注釋
我們可以通過 <#-- 注釋內容 --> 來進行注釋 如下圖
4 freemarker 條件指令
我們可以通過<#if>? <#elseIf> <#else> 進行條件判斷邏輯處理 具體操作如下
條件指令模板內容:
<html> <head> <title>條件指令介紹!</ title> </head> <body> <#-- 條件指令介紹 --> <#if (5 > 4) > 5 比較大 </#if> ------------------------------- <#if (!false)>!false == true </#if> ----------------------------- <#if ("a" == "b")>a 和 b 相同 <#else>a 和 b 不相同 </#if> ----------------------------- <#if ( c == d)>c 和 d 相同 <#elseif ("a" != "b")>c 和 d 不相同<#else>出錯了! </#if> </body> </html>條件指令測試用例:?
這里我們對測試用例進行了封裝,后面的測試用例都將調用 initTemplate?來進行測試
@Testpublic void condition() throws IOException, TemplateException {Map root = new HashMap();root.put("c", "c");root.put("d", "d");initTemplate("condition",root);}public void initTemplate(String templateName,Map root) throws IOException, TemplateException {Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);//指定模板文件的來源String path = FreemarkerDemo.class.getClassLoader().getResource("template").getPath();cfg.setDirectoryForTemplateLoading(new File(path));//這是模板的編碼cfg.setDefaultEncoding("UTF-8");//獲取模板Template template = cfg.getTemplate(templateName+".ftl"); //創建FreeMarker的數據模型 //這是輸出文件File file = new File("D://" +templateName+".html");Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));//將模板與數據模型合并template.process(root, out); out.flush(); out.close(); }5 freemarker list 指令
我們可以通過?<#list 序列 as item>? 來進行序列的遍歷。另外list 還有一些內置的序列的函數
?size:序列的數量
_index :序列中元素的角標
_has_next:是否是當前迭代循環中的最后一項
?sort:對序列中的元素進行排序
?sort_by:根據實例中的具體的否個字段進行排序
?is_enumerable:是否是集合
測試list模板內容
<html> <head> <title>list 指令介紹!</ title> </head> <body> <#list 0..5 as item>${item} </#list> ----------------------------- _index:交標值 ,?size 獲取集合的長度 list的長度:${wordList?size} <#list wordList as word>當前的交標是:${word_index}值是:${word} </#list> -------------------------------- _has_next:是否是當前迭代循環中的最后一項 <#list wordList as word><#if word_has_next>不是最后一項:${word},<#else>是最后一項:${word}</#if>???? ???????????????????? </#list> --------------------------------- 字符串(按首字母排序),數字,日期值 正常遍歷 <#list wordList as word>${word}???????????????????? </#list> 升序 <#list wordList?sort as word>${word}???????????????????? </#list> 降序 <#list wordList?sort?reverse as word>${word}???????????????????? </#list> 反向遍歷 <#list wordList?reverse as word>${word}???????????????????? </#list>------------------------------------- 正常遍歷 <#list productList as p>${p.name}#${p.url}#${p.saleNum}?????????????????????? </#list> 升序 <#list productList?sort_by("saleNum") as p>${p.name}#${p.url}#${p.saleNum}???????????????????? </#list> 降序 <#list productList?sort_by("saleNum")?reverse as p>${p.name}#${p.url}#${p.saleNum}????????????????????? </#list> 反向遍歷 <#list productList?reverse as p>${p.name}#${p.url}#${p.saleNum}?????????????????????? </#list> --------------------------------------- <#list map?keys as item><#if (item == "productMap3")><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}??????????????????????</#list><#else>${map[item]}</#if> </#list> ---------------------------------------- ?is_string:是否是字符串 <#list map?keys as item><#if map[item]?is_string>${map[item]}<#else><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}??????????????????????</#list></#if> </#list> ----------------------------------------- ?is_enumerable:是否是集合 <#list map?keys as item><#if map[item]?is_enumerable><#list map[item] as p>${p.name}#${p.url}#${p.saleNum}??????????????????????</#list><#else>${map[item]}</#if> </#list> </body> </html>list模板內容測試用例:?
@Testpublic void list() throws IOException, TemplateException {Map root = new HashMap();List wordList = new ArrayList();wordList.add(5);wordList.add(3);wordList.add(6);root.put("wordList", wordList);List<Product> productList = new ArrayList<Product>();productList.add(new Product("123.html", "蘋果", 5));productList.add(new Product("13.html", "香蕉", 3));productList.add(new Product("13.html", "芒果", 15));root.put("productList", productList);Map map = new HashMap();map.put("productMap", "a");map.put("productMap2", "b");map.put("productMap3", productList);root.put("map", map);initTemplate("list",root);}list模板內容測試結果:
<html> <head> <title>list 指令介紹!</ title> </head> <body> 012345 ----------------------------- _index:交標值 ,?size 獲取集合的長度 list的長度:3當前的交標是:0值是:5當前的交標是:1值是:3當前的交標是:2值是:6 -------------------------------- _has_next:是否是當前迭代循環中的最后一項不是最后一項:5,不是最后一項:3,是最后一項:6--------------------------------- 字符串(按首字母排序),數字,日期值 正常遍歷5????????????????????3????????????????????6???????????????????? 升序3????????????????????5????????????????????6???????????????????? 降序6????????????????????5????????????????????3???????????????????? 反向遍歷6????????????????????3????????????????????5????????????????????------------------------------------- 正常遍歷蘋果#123.html#5??????????????????????香蕉#13.html#3??????????????????????芒果#13.html#15?????????????????????? 升序香蕉#13.html#3????????????????????蘋果#123.html#5????????????????????芒果#13.html#15???????????????????? 降序芒果#13.html#15?????????????????????蘋果#123.html#5?????????????????????香蕉#13.html#3????????????????????? 反向遍歷芒果#13.html#15??????????????????????香蕉#13.html#3??????????????????????蘋果#123.html#5?????????????????????? ---------------------------------------ab蘋果#123.html#5??????????????????????香蕉#13.html#3??????????????????????芒果#13.html#15?????????????????????? ----------------------------------------ab蘋果#123.html#5??????????????????????香蕉#13.html#3??????????????????????芒果#13.html#15?????????????????????? -----------------------------------------ab蘋果#123.html#5??????????????????????香蕉#13.html#3??????????????????????芒果#13.html#15?????????????????????? </body> </html>6 freemarker assign指令
我們可以通過?assign指令在ftl中進行值的定義
assign指令測試模板內容:
<#assign name="zhuoqianmingyue"> ${name} ----------------------------------------------------------- <#assign product={"name":"蘋果","url":"123.html","saleNum":23} > ${product.name},${product.url},${product.saleNum}?assign指令測試用例:
@Testpublic void assign() throws IOException, TemplateException {Map root = new HashMap();initTemplate("assign",root);}??assign指令測試結果:
7 創建宏
這里的宏 我們可以理解成創建方法。我們可以通過 <#macro>標簽來定義宏。
創建宏模板內容如下
創建宏模板測試用例:
@Testpublic void marco() throws IOException, TemplateException {Map map = new HashMap();initTemplate("macroShow", map);}創建宏模板測試結果:?
嵌套指令<#nested> 可以執行兩次相同的調用
@Testpublic void nested() throws IOException, TemplateException {Map map = new HashMap();initTemplate("nestedShow", map);}8 include指令
?include引入的文件內容freemarker將解析其中的freemarker語法并移交給模板,同時assign的值可以互相調用
include 引入ftl模板
parent.ftl
<html> <body> 我是公共的頁面 ${who}引用啦我! </body> </html>include.ftl?
我是include頁面 <#assign who="include.ftl"> <#include "parent.ftl"/>include指令的測試用例:?
@Testpublic void include() throws IOException, TemplateException {Map map = new HashMap();initTemplate("include", map);}include指令的測試結果:?
include 引入html
在resource 目錄下創建include.html
?
模板內容:
測試用例:
@Testpublic void include2() throws IOException, TemplateException {Map map = new HashMap();initTemplate("include2", map);}測試結果:
9 import指令
import引入的文件內容freemarker將不會解析其中的freemarker語法,同時assign的值可以可以互相調用。他可以創建一個命名空間 通過該命名調用import 模板中的變量和宏
@Testpublic void importFun() throws IOException, TemplateException {Map map = new HashMap();initTemplate("importFun", map);}import 使用宏
@Testpublic void macroImportShow() throws IOException, TemplateException {Map map = new HashMap();initTemplate("macroImportShow", map);}10 freemarker 處理不存在或則為null的值
?當數據模型的key不存在或者key 的value是null 時 我們執行模板引擎進行渲染的化或報如下圖的錯誤
我們可以通過在flt頁面中使用! 或者??if_exists 使其不做任何顯示 通過我們也可以通過??if_exists 和??指令進行是否為空的判斷。
測試模板內容:
${word!} ${word?if_exists} ${product?if_exists.name?if_exists}<#if word??> <#else>word的值為空 </#if> <#if word?if_exists> <#else>word的值為空 </#if>測試用例:?
@Testpublic void ifExists() throws IOException, TemplateException {Map root = new HashMap();String word = null;root.put("word", word);Product product = new Product();product.setName(null);root.put("product", product);initTemplate("ifExists",root);}測試結果:?
?
11?freemarker? 內置函數
具體請參考:https://freemarker.apache.org/docs/ref_builtins.html
我們這里介紹一下經常使用的內置函數 ,我們上面在介紹list的時候 使用的 ?size就只一個內置函數
11.1字符串
?length :字符串的長度 例如:${"zhuoqianmingyue"?length}
?index_of :字符串中字符的位置交標?例如:${"zhuoqianmingyue"?index_of('yue')}
?substring:截取字符串?例如:${"zhuoqianmingyue"?substring(1)} ${"zhuoqianmingyue"?substring(1,2)}
?trim:去掉字符串的空格?例如:${" Hello world "?trim}
?contains:是否包含否個字符?例如:${"Hello world "?contains('Hello')?string}
?date:日期的轉換? ,?datetime datetime的轉換?
<#assign date1="2009-10-12"?date("yyyy-MM-dd")>
<#assign date2="09:28:20"?datetime("HH:mm:ss")>
?string:字符串格式輸出?例如:${date1?string}
?is_string:是否是字符串?例如:${date1?is_string?string}
以上語法模板內容
length: ${"zhuoqianmingyue"?length} index_of: ${"zhuoqianmingyue"?index_of('yue')} substring: ${"zhuoqianmingyue"?substring(1)} ${"zhuoqianmingyue"?substring(1,2)} trim: ${" Hello world "?trim} contains:${"Hello world "?contains('Hello')?string}<#assign date1="2009-10-12"?date("yyyy-MM-dd")> <#assign date2="09:28:20"?datetime("HH:mm:ss")> ${date1?is_string?string} ${date1?string} ${date2?string}測試用例:
@Testpublic void string() throws IOException, TemplateException {Map map = new HashMap();initTemplate("string", map);}測試結果:
11.2 日期
.now 獲取當前時間
日期格式轉換
<#assign aDateTime = .now> ${.now} ${aDateTime?string["dd.MM.yyyy, HH:mm"]} ${aDateTime?string["EEEE, MMMM dd, yyyy, hh:mm a '('zzz')'"]} ${aDateTime?string["EEE, MMM d, ''yy"]} ${aDateTime?string.yyyy} @Testpublic void date() throws IOException, TemplateException {Map map = new HashMap();initTemplate("date", map);}11.3 序列 (Sequence)
?size ?reverse ?sort ?sort_by 我們已經在list 指令進行了演示 這里就不在做介紹了
?chunk:序列分塊遍歷
?first ?last:獲取序列中的第一個和最后一個元素
?join:拼接序列中的內容
?seq_contains:序列中是否包含某個元素
?seq_index_of:序列中元素的交標
<#assign seq = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']><#list seq?chunk(4) as row><#list row as cell>${cell} </#list> </#list><#list seq?chunk(4, '-') as row><#list row as cell>${cell} </#list> </#list> ---------------------------------------------${seq[1]} ${seq?first} ${seq?last} ----------------------------------------------<#assign colors = ["red", "green", "blue"]>${colors?join(", ")}--------------------------------------------- <#assign x = ["red", 16, "blue", "cyan"]> "blue": ${x?seq_contains("blue")?string("yes", "no")} "yellow": ${x?seq_contains("yellow")?string("yes", "no")} 16: ${x?seq_contains(16)?string("yes", "no")} "16": ${x?seq_contains("16")?string("yes", "no")} ------------------------------------------------- <#assign colors = ["red", "green", "blue"]> ${colors?seq_index_of("blue")} ${colors?seq_index_of("red")} ${colors?seq_index_of("purple")}測試用例:
@Testpublic void sequences() throws IOException, TemplateException {Map map = new HashMap();initTemplate("sequences", map);}?
11.4 數字:
abs:絕對值? ? 2.3.20
round:四舍五入
floor:向下取整
ceiling:向上取整
string.number:整數數字輸出
string.currency:貨幣格式輸出
string.percent:百分數格式輸出
?
?string["0.##"]:數字顯示2為小數
?string["000.00"]:小數左面不夠0補齊
${-5?abs} ${4.5?round} ${4.4?round} ${4.5?floor} ${4.5?ceiling}<#assign x = 42> ${x} ${x?string} ${x?string.number} ${x?string.currency} ${x?string.percent} ${1.2345?string["0.##"]} ${1.2345?string["000.00"]} @Testpublic void number() throws IOException, TemplateException {Map map = new HashMap();initTemplate("number", map);}11.5 has_api
下面的內置函數返回的結果都是布爾型的
is_string :是否是String
is_number :是否是數字
is_boolean :是否是布爾類型
is_date :是否是日期
is_macro :是否是宏
is_sequence:是否是序列
? ?
?
總結
以上是生活随笔為你收集整理的freemarker Java 模板引擎 基本语法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python可以跨平台吗_python是
- 下一篇: 华为G610开机第一屏G3替换教程