FreeMarker的基礎語法使用 && 心得和技巧

FreeMarker語言

FreeMarker語言概述

FreeMarker是一個模板引擎,一個基於模板生成文本輸出的通用工具,使用純Java編寫。html

FreeMarker被設計用來生成HTML Web頁面,特別是基於MVC模式的應用程序java

雖然FreeMarker具備一些編程的能力,但一般由Java程序準備要顯示的數據,由FreeMarker生成頁面,經過模板顯示準備的數據(以下圖)程序員

FreeMarker不是一個Web應用框架,而適合做爲Web應用框架一個組件。web

FreeMarker與容器無關,由於它並不知道HTTP或Servlet;FreeMarker一樣能夠應用於非Web應用程序環境。數據庫

FreeMarker更適合做爲Model2框架(如Struts)的視圖組件,你也能夠在模板中使用JSP標記庫。apache

FreeMarker是免費的。編程

FreeMarker特性

通用目標

可以生成各類文本:HTML、XML、RTF、Java源代碼等等瀏覽器

易於嵌入到你的產品中:輕量級;不須要Servlet環境服務器

插件式模板載入器:能夠從任何源載入模板,如本地文件、數據庫等等app

你能夠按你所需生成文本:保存到本地文件;做爲Email發送;從Web應用程序發送它返回給Web瀏覽器

強大的模板語言

全部經常使用的指令:include、if/elseif/else、循環結構

在模板中建立和改變變量

幾乎在任何地方均可以使用複雜表達式來指定值

命名的宏,能夠具備位置參數和嵌套內容

名字空間有助於創建和維護可重用的宏庫,或者將一個大工程分紅模塊,而沒必要擔憂名字衝突

輸出轉換塊:在嵌套模板片斷生成輸出時,轉換HTML轉義、壓縮、語法高亮等等;你能夠定義本身的轉換

通用數據模型

FreeMarker不是直接反射到Java對象,Java對象經過插件式對象封裝,以變量方式在模板中顯示

你可使用抽象(接口)方式表示對象(JavaBean、XML文檔、SQL查詢結果集等等),告訴模板開發者使用方法,使其不受技術細節的打擾

爲Web準備

在模板語言中內建處理典型Web相關任務(如HTML轉義)的結構

可以集成到Model2 Web應用框架中做爲JSP的替代

支持JSP標記庫

爲MVC模式設計:分離可視化設計和應用程序邏輯;分離頁面設計員和程序員

智能的國際化和本地化

字符集智能化(內部使用UNICODE)

數字格式本地化敏感

日期和時間格式本地化敏感

非US字符集能夠用做標識(如變量名)

多種不一樣語言的相同模板

強大的XML處理能力

<#recurse> 和<#visit>指令(2.3版本)用於遞歸遍歷XML樹。在模板中清楚和直覺的訪問XML對象模型。開源論壇 JForum 就是使用了 FreeMarker 作爲頁面模板。

第一個FreeMarker程序

1.      創建一個普通的java項目:testFreeMarker

2.      引入freemarker.jar包

3.      在項目目錄下創建模板目錄:templates

4.      在templates目錄下,創建a.ftl模板文件,內容以下:

 

    • 你好啊,${user},今天你的精神不錯!

 

5.      創建com.sxt.test.freemarker包,而後創建Test1.java文件,內容以下:

package com.sxt.test.freemarker;

 

import java.io.File;

import java.io.OutputStreamWriter;

import java.io.Writer;

import java.util.HashMap;

import java.util.Map;

 

import freemarker.template.Configuration;

import freemarker.template.DefaultObjectWrapper;

import freemarker.template.Template;

 

public class Test1 {

         public static void main(String[] args) throws Exception {

                   //建立Freemarker配置實例

                   Configuration cfg = new Configuration();

                  

                   cfg.setDirectoryForTemplateLoading(new File("templates"));

                  

                   //建立數據模型

                   Map root = new HashMap();

                   root.put("user", "老高");

                  

                   //加載模板文件

                   Template t1 = cfg.getTemplate("a.ftl");

                  

                   //顯示生成的數據,//將合併後的數據打印到控制檯

       Writer out = new OutputStreamWriter(System.out);

       t1.process(root, out);

       out.flush();

 

       //顯示生成的數據,//將合併後的數據直接返回成字符串!

//     StringWriter out = new StringWriter();  

//     t1.process(root, out);

//     out.flush();

//     String temp = out.toString();

//     System.out.println(temp);        }

}

6.      編譯和運行Test1.java文件,控制檯打印:

 

數據類型

1、直接指定值

直接指定值能夠是字符串、數值、布爾值、集合及Map對象。
1. 字符串
直接指定字符串值使用單引號或雙引號限定。字符串中可使用轉義字符」\"。若是字符串內有大量的特殊字符,則能夠在引號的前面加上一個字母r,則字符串內的全部字符都將直接輸出。

2. 數值
數值能夠直接輸入,不須要引號。FreeMarker不支持科學計數法。

3. 布爾值
直接使用true或false,不使用引號。

4. 集合
集合用中括號包括,集合元素之間用逗號分隔。
使用數字範圍也能夠表示一個數字集合,如1..5等同於集合[1, 2, 3, 4, 5];一樣也能夠用5..1來表示[5, 4, 3, 2, 1]。

5. Map對象
Map對象使用花括號包括,Map中的key-value對之間用冒號分隔,多組key-value對之間用逗號分隔。
注意:Map對象的key和value都是表達式,但key必須是字符串。

 

6. 時間對象

root.put("date1", new Date());

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

 

7. JAVABEAN的處理

         Freemarker中對於javabean的處理跟EL表達式一致,類型可自動轉化!很是方便!

2、輸出變量值

FreeMarker的表達式輸出變量時,這些變量能夠是頂層變量,也能夠是Map對象的變量,還能夠是集合中的變量,並可使用點(.)語法來訪問Java對象的屬性。

1. 頂層變量
所謂頂層變量就是直接放在數據模型中的值。輸出時直接用${variableName}便可。

2. 輸出集合元素
可 以根據集合元素的索引來輸出集合元素,索引用中括號包括。如: 輸出[「1」, 「2」, 「3」]這個名爲number的集合,能夠用${number[0]}來輸出第一個數字。FreeMarker還支持用number[1..2]來表示原 集合的子集合[「2」, 「3」]。

3. 輸出Map元素
對於JavaBean實例,FreeMarker同樣把它看做屬性爲key,屬性值爲value的Map對象。
輸出Map對象時,可使用點語法或中括號語法,以下面的幾種寫法的效果是同樣的:
            book.author.name                                                                                                                    
            book.author["name"]                                                                                                                    
            book["author"].name                                                                                                                     
            book["author"]["name"]                                                                                                                  
使用點語法時,變量名字有和頂層變量同樣的限制,但中括號語法沒有任何限制。

3、字符串操做

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

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

 

4、集合鏈接操做
      鏈接集合的運算符爲「+」

5、Map鏈接操做
   Map鏈接操做的運算符爲「+」

6、算術運算符
   FreeMarker表達式中支持「+」、「-」、「*」、「/」、「%」運算符。

7、比較運算符

表達式中支持的比較運算符有以下幾種:
1. =(或者==):判斷兩個值是否相等;
2. !=:判斷兩個值是否不相等;
注: =和!=能夠用做字符串、數值和日期的比較,但兩邊的數據類型必須相同。並且FreeMarker的比較是精確比較,不會忽略大小寫及空格。
3. >(或者gt):大於
4. >=(或者gte):大於等於
5. <(或者lt):小於
6. <=(或者lte):小於等於
注: 上面這些比較運算符能夠用於數字和日期,但不能用於字符串。大部分時候,使用gt比>有更好的效果,由於FreeMarker會把>解釋成標籤的結束字符。可使用括號來避免這種狀況,如:<#if (x>y)>。

if else 語句測試:

<#if num0 gt 18>  <#--不是使用>,大部分時候,freemarker會把>解釋成標籤結束! -->

    及格!

<#else>

    不及格!

</#if>

root.put("num0", 18);

 

8、邏輯運算符

1. &&: 邏輯與;
2. ||:邏輯或;
3. !:邏輯非
邏輯運算符只能用於布爾值。

9、內建函數

FreeMarker提供了一些內建函數來轉換輸出,能夠在任何變量後緊跟?,?後緊跟內建函數,就能夠經過內建函數來轉換輸出變量。

字符串相關經常使用的內建函數:
1. html:對字符串進行HTML編碼;
2. cap_first:使字符串第一個字母大寫;
3. lower_case:將字符串轉成小寫;
4. upper_case:將字符串轉成大寫;

集合相關經常使用的內建函數:
1. size:得到集合中元素的個數;

數字值相關經常使用的內建函數:
1. int:取得數字的整數部分。

 

舉例:

root.put("htm2", "<b>粗體</b>");

內建函數:

${htm2?html}

 

10、空值處理運算符

FreeMarker的變量必須賦值,不然就會拋出異常。而對於FreeMarker來講,null值和不存在的變量是徹底同樣的,由於FreeMarker沒法理解null值。
FreeMarker提供兩個運算符來避免空值:
1. !:指定缺失變量的默認值;
2. ??:判斷變量是否存在。
!運算符有兩種用法:variable!或variable!defaultValue。第一種用法不給變量指定默認值,代表默認值是空字符串、長度爲0的集合、或長度爲0的Map對象。
使用!運算符指定默認值並不要求默認值的類型和變量類型相同。

測試空值處理:

<#-- ${sss} 沒有定義這個變量,會報異常! -->

${sss!} <#--沒有定義這個變量,默認值是空字符串! -->

${sss!"abc"} <#--沒有定義這個變量,默認值是字符串abc! -->

 

         ??運算符返回布爾值,如:variable??,若是變量存在,返回true,不然返回false。

        

 

數據類型常見示例

 直接指定值

   字符串 : "Foo"或 者'Foo'或"It's\"quoted\""或r"C:\raw\string"

   數字:123.45

   布爾值:true,false

   序列:["foo","bar", 123.45], 1..100

   哈希表:{"name":"greenmouse", "price":150}

   檢索變量    頂層變量:user

   從哈希表中檢索數據:user.name,user[「name」]

   從序列中檢索:products[5]

   特殊變量:.main

   字符串操做

   插值(或鏈接):"Hello${user}!"(或"Free" + "Marker")

   獲取一個字符:name[0]

   序列操做

   鏈接:users +["guest"]

   序列切分:products[10..19]  或  products[5..]

   哈希表操做

   鏈接:passwords+ {"joe":"secret42"}

   算數運算: (x *1.5 + 10) / 2 - y % 100

   比 較 運 算 : x == y,   x != y,  x < y,   x > y,   x >= y,  x <= y,

x &lt; y,  等等

    邏輯操做:!registered&& (firstVisit || fromEurope)

    內建函數:name?upper_case

    方法調用:repeat("What",3)

   處理不存在的值

   默認值:name!"unknown"  或者(user.name)!"unknown"  或者

name! 或者  (user.name)!

   檢測不存在的值:name??或者(user.name)??

        參考:運算符的優先級

模板開發語句

最簡單的模板是普通  HTML  文件(或者是其餘任何文本文件—FreeMarker  自己不屬於HTML)。當客戶端訪問頁面時,FreeMarker要發送 HTML 代碼至客戶端瀏覽器端顯示。若是想要頁面動起來,就要在 HTML 中放置能被 FreeMarker 所解析的特殊部分。

   

${…}:FreeMarker 將會輸出真實的值來替換花括號內的表達式,這樣的表達式被稱爲

interpolations 插值,能夠參考第上面示例的內容。

 

   FTL tags 標籤(FreeMarker  模板的語言標籤):FTL 標籤和 HTML 標籤有一點類似,可是它們是  FreeMarker 的指令並且是不會直接輸出出來的東西。這些標籤的使用通常以符號#開頭。(用戶自定義的 FTL 標籤使用@符號來代替#,但這是更高級的主題內容了,後面會詳細地討論)

  

Comments 註釋:FreeMarker的註釋和 HTML 的註釋類似,可是它用<#--和-->來分隔的。任何介於這兩個分隔符(包含分隔符自己)之間內容會被 FreeMarker  忽略,就不會

輸出出來了。

 

    其餘任何不是  FTL  標籤,插值或註釋的內容將被視爲靜態文本,這些東西就不會被

FreeMarker 所解析,會被按照原樣輸出出來。

 

   directives指令:就是所指的  FTL  標籤。這些指令在  HTML  的標籤(如<table>和

</table>)和 HTML 元素(如 table 元素)中的關係是相同的。(若是如今你還不能區

分它們,那麼把「FTL 標籤」和「指令」看作是同義詞便可。)

if指令

root.put("random", new Random().nextInt(100));

------------------------------------------------

if語句測試:

${user}是<#if user=="老高">咱們的老師</#if>

------------------------------------------------

if else 語句測試:

<#if num0 gt 18>  <#--不是使用>,大部分時候,freemarker會把>解釋成標籤結束! -->

    及格!

<#else>

    不及格!

</#if>

---------------------------------------------------

if else if else語句測試:

<#if random gte 90>

    優秀!

<#elseif random gte 80>

    良好!

<#else>

    通常! 

</#if>

----------------------------------------------------

 

 

list指令

       List list = new ArrayList();

       list.add(new Address("中國","北京"));

       list.add(new Address("中國","上海"));

       list.add(new Address("美國","紐約"));

       root.put("lst", list);

測試list指令:

<#list lst as dizhi >

    <b>${dizhi.country}</b> <br/>

</#list>

 

思考問題:<c:forEach> status屬性。在此處如何實現?

 

控制檯打印:

測試list語句:

    <b>中國</b> <br/>

    <b>中國</b> <br/>

    <b>美國</b> <br/>

 

include指令

增長被包含文件,放於templates目錄下:

文件內容以下:

 

 

模板文件中代碼以下:

測試include指令:

<#include "included.txt" />

 

 

自定義指令(macro指令)

<#macro m1>   <#--定義指令m1 -->

    <b>aaabbbccc</b>

    <b>dddeeefff</b>

</#macro>

<@m1 /><@m1 />  <#--調用上面的宏指令 -->

 

定義帶參的宏指令:

<#macro m2 a b c >

    ${a}--${b}--${c}

</#macro>

<@m2 a="老高" b="老張" c="老馬" />

 

nested指令:

<#macro border>

  <table border=4 cellspacing=0 cellpadding=4><tr><td>

    <#nested>

  </td></tr></table>

</#macro>

<@border >表格中的內容!</@border>

 

歐陽鴻:宏指令中,有沒有相似於方法的返回值?

命名空間

當運行 FTL 模板時,就會有使用assign 和 macro 指令建立的變量的集合(多是空的),能夠從前一章節來看如何使用它們。像這樣的變量集合被稱爲 namespace 命名空間。在簡單的狀況下能夠只使用一個命名空間,稱之爲 main namespace 主命名空間。由於一般只使用本頁上的命名空間,因此就沒有意識到這點。

    若是想建立能夠重複使用的宏,函數和其餘變量的集合,一般用術語來講就是引用

library 庫。使用多個命名空間是必然的。只要考慮你在一些項目中,或者想和他人共享使用的時候,你是否有一個很大的宏的集合。但要確保庫中沒有宏(或其餘變量)名和數據模型中變量同名,並且也不能和模板中引用其餘庫中的變量同名。一般來講,變量由於名稱衝突也會相互衝突。因此要爲每一個庫中的變量使用不一樣的命名空間。

 

定義b.ftl文件:

<#macro copyright date>

  <p>Copyright (C) ${date} 北京尚學堂.</p>

</#macro>

<#assign mail = "bjsxt@163.com">

 

在a.ftl文件中引入b.ftl,從而可使用b.ftl中定義的宏和變量:

測試命名空間:

<#import "b.ftl" as bb  />

<@bb.copyright date="2010-2011" />

${bb.mail}

<#assign mail="my@163.com"  />

${mail}

<#assign mail="my@163.com" in bb  />

${bb.mail}

 

執行後,控制檯打印:

測試命名空間:

  <p>Copyright (C) 2010-2011 北京尚學堂.</p>

bjsxt@163.com

my@163.com

my@163.com

 

命名空間命名規則

若是你爲 Example 公司工做,它們擁有 www.example.com 網的主頁,你的工做是開發

一個部件庫,那麼要引入你所寫的 FTL 的路徑應該是:

/lib/example.com/widget.ftl

 

注意到 www 已經被省略了。第三次路徑分割後的部分能夠包含子目錄,能夠像下面這

樣寫:

        /lib/example.com/commons/string.ftl

一個重要的規則就是路徑不該該包含大寫字母,爲了分隔詞語,使用下劃線_,就像

wml_form(而不是 wmlForm)。

 

若是你的工做不是爲公司或組織開發庫,也要注意,你應該使用項目主頁的 URL,好比

/lib/example.sourceforge.net/example.ftl或/lib/geocities.com/jsmith/example.ftl。

 

在Servlet中使用Freemarker

參考Freemarker包中example目錄下webapp1項目!

 

struts2中整合FreeMarker

1.解壓struts2-core-X.X.X.jar文件,把在META-INF文件夾下面的struts-tags.tld文件複製到WEB-INF文件夾下。   將freemark的jar導入到工程中

 

2.在web.xml文件中配置freemark同時啓動JSPSupportServlet.代碼以下:

<servlet>
        <servlet-name>freemarker</servlet-name>
        <servlet-class>
            freemarker.ext.servlet.FreemarkerServlet
        </servlet-class>
        <!--下面的配置freemarke的ftl文件的位置 -->
        <init-param>
            <param-name>TemplatePath</param-name>
            <param-value>/</param-value>
        </init-param>
        <!-- 是否和服務器(tommcat)一塊兒啓動。-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>freemarker</servlet-name>
        <url-pattern>*.ftl</url-pattern>
    </servlet-mapping>


<servlet>
  <!-- define a JspSupportServlet Object -->
  <servlet-name>JspSupportServlet</servlet-name>
  <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
  <!-- setting JspSupportServlet auto start -->
  <load-on-startup>1</load-on-startup>
 </servlet>

 

3.在FreeMarker模板中使用assign指令導入標籤庫。代碼以下

<#assign s=JspTaglibs["/WEB-INF/struts-tags.tld"] /> 注:這裏我把struts-tags.tld放在WEB-INF下面

if

 

詳情可見web項目:testFreeMarker2

 

 

 

做業:

1.      使用list標籤遍歷list容器時,如何獲取索引(下劃線加index便可獲取):

 

-------------------------------------

測試list索引_index

<#list list as city>

         ${city}<br/>${city_index}

         <#if city_index==1>

                   <#break>

         </#if>

</#list>

**************************************

測試list中國_has_next

<#list list as city>

         ${city}<br/>${city_index}

         <#if city_has_next>

                   我有下一項!------- ${city_index}

         </#if>

</#list>

 

2.      調用對象或類的方法?

3.      .main特殊變量的做用

4.      定義的macro可否有返回值,有的話,怎麼處理?

 

 

 

 

=======================華麗分割線================

一、對activityMenu (集合對象)進行遍歷:

 

 

知識點:集合對象判空、集合遍歷、使用索引、if條件判斷

 

二、${MenuList?size}  ——>獲得List集合的個數。  <#if (a_list?size >= 15)> :  判斷大小

 

三、若是是Long類型會有」,」區分,處理方式${c_List.refId?c}

相關文章
相關標籤/搜索