1. 程式人生 > >【學習筆記】初識FreeMarker簡單使用

【學習筆記】初識FreeMarker簡單使用

als 大小 宋體 屬性 list mage equal port template

楔子:

   之前在和同事討論,同事說“jsp技術太古老了,有幾種頁面技術代替,比如FreeMarker、Velocity、thymeleaf,jsp快廢棄了……”雲雲。我這一聽有點心虛……我在後端部分越刨越深,頁面裝配技術什麽的好像只知道有jsp……趁放假自己補補課啦~

簡介:

  FreeMarker是一個模板引擎,一個基於模板生成文本輸出的通用工具,純Java編寫。類似jsp,簡單來講就是模板加數據模型,然後輸出頁面。

技術分享圖片

圖片來自尚學堂課件,侵權刪

  相對於jsp,FreeMarker的性能略差幾十毫秒,但是復雜頁面上性能比jsp更佳。

  而且最好的一點,我感覺應該是可以直接把美工寫好的html放進模板中使用(無需加jsp頭等),FreeMarker自帶的一些標簽用著也很簡單。FreeMarker的模板文件格式為ftl,也可以直接用html

  FreeMarker可以應用更多的場景,與容器無關;而jsp要求有JVM環境,只能應用於web應用中。

HelloWorld:

  第一個FreeMarker代碼

新建一個Java project,起名為 FreeMarker,在src外部新建一個文件夾命名為templates,如圖:

技術分享圖片

在templates中新建一個file,命名為first.ftl,添加如下代碼(其中的表達式類似於EL表達式):

hello,${user},這是你的第一個FreeMarker程序!

下載FreeMarker.jar並引入項目

新建FirstFreeMarker類,代碼如下:

 1 package
com.hellxz; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.io.OutputStreamWriter; 6 import java.io.Writer; 7 import java.util.HashMap; 8 import java.util.Map; 9 10 import freemarker.template.Configuration; 11 import freemarker.template.Template; 12 import freemarker.template.TemplateException;
13 14 /** 15 * 第一個FreeMarker程序 16 * 17 * @author hellxz 18 */ 19 public class FirstFreeMarker { 20 21 @SuppressWarnings({"rawtypes","unchecked"}) 22 public static void main(String[] args) throws IOException, TemplateException { 23 // 創建Freemarker配置實例 24 Configuration cfg = new Configuration(); 25 cfg.setDirectoryForTemplateLoading(new File("templates")); 26 27 // 創建數據模型 28 Map root = new HashMap(); 29 root.put("user", "老張"); 30 31 // 加載模板文件 32 Template t1 = cfg.getTemplate("first.ftl"); 33 34 // 顯示生成的數據,將合並後的數據打印到控制臺 35 Writer out = new OutputStreamWriter(System.out); 36 t1.process(root, out); 37 out.flush(); 38 out.close(); 39 40 } 41 42 }

運行代碼,查看輸出:

hello,老張,這是你的第一個FreeMarker程序!

測試舉例:

本例子基本涵蓋了大部分FreeMarker特有的屬性,參考Java語言不同點寫就,相同點並沒有測試。通過觀察代碼可以很清晰的看出這些函數、指令的使用方法

新建一個Address類:

 1 package com.hellxz;
 2 
 3 /**
 4  * 地址
 5  * 
 6  * @author hellxz
 7  */
 8 public class Address {
 9 
10     private String country; // 國家
11     private String city; // 城市
12 
13     //getters & setters
14     public String getCountry() {
15         return country;
16     }
17 
18     public void setCountry(String country) {
19         this.country = country;
20     }
21 
22     public String getCity() {
23         return city;
24     }
25 
26     public void setCity(String city) {
27         this.city = city;
28     }
29 
30     public Address(String country, String city) {
31         this.country = country;
32         this.city = city;
33     }
34 }

新建一個TestFreeMarker類,代碼如下:

 1 package com.hellxz;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.io.OutputStreamWriter;
 6 import java.io.Writer;
 7 import java.util.ArrayList;
 8 import java.util.HashMap;
 9 import java.util.Map;
10 import java.util.Random;
11 
12 import freemarker.template.Configuration;
13 import freemarker.template.Template;
14 import freemarker.template.TemplateException;
15 
16 /**
17  * FreeMarker Test
18  * 
19  * @author hellxz
20  */
21 public class TestFreeMarker {
22 
23     @SuppressWarnings({ "rawtypes", "unchecked" })
24     public static void main(String[] args) throws IOException, TemplateException {
25         //1.創建配置文件
26         Configuration conf = new Configuration();
27         //2.設置模板目錄
28         conf.setDirectoryForTemplateLoading(new File("templates"));
29         //3.數據模型
30         Map<String,Object> map = new HashMap<>();
31         map.put("user", "老張");
32         map.put("random",new Random().nextInt(100));
33         //新建一個list放入map中,用於測試遍歷list操作
34         ArrayList list = new ArrayList();
35         list.add(new Address("中國","上海"));
36         list.add(new Address("日本","東京"));
37         map.put("list", list);
38         //測試內建函數
39         map.put("html5", "<b>大寫的文字</b>");
40         map.put("name", "hellxz");
41         map.put("upper", "ABCDEF");
42         //4.獲取模板文件
43         Template template = conf.getTemplate("a.ftl");
44         //5.輸出流
45         Writer out = new OutputStreamWriter(System.out);
46         //6.生成文件流輸出
47         template.process(map, out);
48         out.flush();
49         out.close();
50     }
51 }

在templates文件夾下新建a.ftl

  1 hello,${user},今天看起來很精神嘛!
  2 ----------------------------------
  3 if分支語句測試:
  4 <#if user=="老張">
  5         老張!
  6 </#if>
  7 ----------------------------------
  8 if else 分支測試:
  9 <#if user=="老李">
 10         老李
 11 <#else>
 12         老張
 13 </#if>
 14 ----------------------------------
 15 if else if else 測試:
 16 因為大於小於號等會被轉義,使用簡寫代替比較符號
 17 gt(great than的簡寫) 代替 >
 18 lt(less than的簡寫) 代替 <
 19 gte(great than equal的簡寫) 代替 >=
 20 lte (less than equal的簡寫) 代替 <=
 21 <#if random gt 80>
 22         優秀
 23 <#elseif random gt 60>
 24         及格
 25 <#else>
 26         不及格
 27 </#if>
 28 ----------------------------------
 29 遍歷list測試:
 30 <#list list as addr>
 31         ${addr.country} ${addr.city}
 32 </#list>
 33 ----------------------------------
 34 include包含測試:
 35 <#include "include.txt"/>
 36 ----------------------------------
 37 macro無參函數(宏函數)測試:
 38 定義函數:
 39 <#macro m1>
 40     我是函數內容
 41 </#macro>
 42 調用函數測試:
 43 <@m1/><@m1/><#--這是註釋內容:這裏調用了兩次函數-->
 44 ----------------------------------
 45 macro帶參函數<#--(格式為"<#macro 函數名 [變量1 變量2 變量3 ……] </#macro>")-->:
 46 <#macro cc a b c>
 47     ${a}/${b}/${c}
 48 </#macro>
 49 調用測試<#--(格式為:"<@函數名 [變量1值 變量2值 變量3值 ……] </#macro>")-->:
 50 <@cc "中" "明" "月"/>
 51 ----------------------------------
 52 nested測試:
 53 用於一大段代碼的嵌入
 54 <#macro border>
 55     <html>
 56         <head>
 57             <body>
 58                 <#nested/>
 59             </body>
 60         </head>
 61     </html>
 62 </#macro>
 63 向nested部分添加內容:
 64 <@border>
 65                 <h1>我是nested的內容</h1>
 66 </@border>
 67 ----------------------------------
 68 測試命名空間:
 69 <#import "b.ftl" as bb  />
 70 <@bb.copyright date="2010-2011" />
 71 ${bb.mail}
 72 <#assign mail="[email protected]"  />
 73 ${mail}
 74 <#assign mail="[email protected]" in bb  />
 75 ${bb.mail}
 76 -----------------------------------
 77 聲明、指定變量assign:
 78 測試數據類型:
 79 <#assign ss="hellxz"/>
 80 文本型:${ss}
 81 <#assign s1=1 />
 82 數值型:${s1}
 83 <#assign s2=true/>
 84 布爾型:<#if s2>布爾型</#if>
 85 -------------------------------------
 86 字符串常見內建函數:
 87 html轉義:${html5?html}
 88 cap_first(首字母大寫):${name?cap_first}
 89 upper_case(轉大寫):${name?upper_case}
 90 lower_case(轉小寫):${upper?lower_case}
 91 數值常見內建函數:
 92 int(取整數部分)
 93 集合內建函數:
 94 size(取集合大小)
 95 ------------------------------------
 96 字符串空值處理:
 97 FreeMarker不支持空值,如果為空直接報錯
 98 沒有定義直接引用
 99 <#-- ${sss} 直接報錯了-->
100 空值處理:
101 ${sss!}<#-- 為空則輸出空字符串 -->
102 ${sss!"default"} <#--設置默認值,為空自動使用-->
103 ------------------------------------------
104 ??布爾值處理
105 <#if user??>
106 如果該值存在,返回true,相當於 if user != null
107 <#else>
108 該值不存在返回false
109 </#if>

新建b.ftl 用於測試命名空間

1 <#macro copyright date>
2   <p>Copyright (C) ${date} 北京尚學堂.</p> 
3 </#macro> 
4 <#assign mail = "[email protected]">

在templates下新建include.txt,用於測試include指令

我是被包含的內容!

運行TestFreeMarker,查看輸出(這裏為了方便比較,加上行號):

 1 hello,老張,今天看起來很精神嘛!
 2 ----------------------------------
 3 if分支語句測試:
 4         老張!
 5 ----------------------------------
 6 if else 分支測試:
 7         老張
 8 ----------------------------------
 9 if else if else 測試:
10 因為大於小於號等會被轉義,使用簡寫作為比較符號
11 gt=great than = >
12 lt=less than = <
13 gte = great than equal = >=
14 lte = less than equal = <=
15         及格
16 ----------------------------------
17 遍歷list測試:
18         中國 上海
19         日本 東京
20 ----------------------------------
21 include包含測試:
22 我是被包含的內容!
23 ----------------------------------
24 macro無參函數(宏函數)測試:
25 定義函數:
26 調用函數測試:
27     我是函數內容
28     我是函數內容
29 ----------------------------------
30 macro帶參函數:
31 調用測試:
32     中/明/33 ----------------------------------
34 nested測試:
35 用於一大段代碼的嵌入
36 向nested部分添加內容:
37     <html>
38         <head>
39             <body>
40                 <h1>我是nested的內容</h1>
41             </body>
42         </head>
43     </html>
44 ----------------------------------
45 測試命名空間:
46   <p>Copyright (C) 2010-2011 北京尚學堂.</p> 
47 bjsxt@163.com
48 my@163.com
49 my@163.com
50 -----------------------------------
51 聲明、指定變量assign:
52 測試數據類型:
53 文本型:hellxz
54 數值型:1
55 布爾型:布爾型
56 -------------------------------------
57 字符串常見內建函數:
58 html轉義:&lt;b&gt;大寫的文字&lt;/b&gt;
59 cap_first(首字母大寫):Hellxz
60 upper_case(轉大寫):HELLXZ
61 lower_case(轉小寫):abcdef
62 數值常見內建函數:
63 int(取整數部分)
64 集合內建函數:
65 size(取集合大小)
66 ------------------------------------
67 字符串空值處理:
68 FreeMarker不支持空值,如果為空直接報錯
69 沒有定義直接引用
70 空值處理:
71 
72 default 
73 ------------------------------------------
74 ??布爾值處理
75 如果該值存在,返回true,相當於 if user != null

看了一下漏了一個日期處理,這裏補一下:

map.put("date", new Date());

a.ftl中模板寫法:

${date?string("yyyy-MM-dd HH:mm:ss")}

輸出:

2018-02-18 16:18:10

字符串連接
字符串連接有兩種語法:
1) 使用${..}#{..}在字符串常量內插入表達式的值;
(2) 直接使用連接運算符“+”連接字符串。
如,下面兩種寫法等效:
${"Hello, ${user}"}
${"Hello, " + user + "!"}
有一點需要註意: ${..}只能用於文本部分作為插值輸出,而不能用於比較等其他用途,如:
<#if ${isBig}>Wow!</#if>
<#if "${isBig}">Wow!</#if>
應該寫成:
<#if isBig>Wow!</#if>

截取子串
截取子串可以根據字符串的索引來進行,如果指定一個索引值,則取得字符串該索引處的字符;如果指定兩個索引值,則截取兩個索引中間的字符串子串。如:
<#assign number="01234">
${number[0]} <#-- 輸出字符0 -->
${number[0..3]} <#-- 輸出子串“0123” -->

本文為FreeMarker簡單的語法使用,servlet以及struts部分見下篇博客

【學習筆記】初識FreeMarker簡單使用