FreeMarker筆記 第四章 其它

來源:互聯網
上載者:User

標籤:winform   style   blog   http   color   io   os   使用   java   

4.1 自訂指令 4.1.1 簡介

自訂指令可以使用macro指令來定義。Java程式員若不想在模板中實現定義指令,而是在Java語言中實現指令的定義,這時可以使用freemarker.template.TemplateDirectiveModel類來擴充,後邊會講。 4.1.2 基本內容

宏是有一個變數名的模板片段。你可以在模板中使用宏作為自訂指令,這樣就能進行重複性的工作。例如,建立一個宏變數來列印大號的”hello Joe!“;

<#macro greet>    <font size="+2">Hello Joe!</font></#macro>

可以在FTL標記中通過@代替#來使用自訂指令。

<@greet></@greet>
4.1.3 參數

我們僅在greet宏中定義一個變數,person;

<#macro greet person>    <font size="+2">Hello ${person}!</font></#macro>

那麼可以這樣使用宏:

<@greet person="Fred"/>and<@greet person="Batman"/>

可以去掉雙引號, <@greet person=Fred/>

多個參數時,可以設定預設值,要不然的話使用的時候必須指定對應的多個參數:

<#macro greet person color="black">    <font size="+2" color="${color}">Hello ${person}!</font></#macro>

那麼就可以這樣使用了

<@greet person="Fred"/>
執行個體

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/macro.ftl

    <h2>沒有參數</h2>    <p>        <#macro greet>            <font size="+2">Hello Joe!</font>        </#macro>        <@greet/>    </p>    <h2>有參數</h2>    <p>        <#macro greet person>            <font size="+2">Hello ${person}!</font>        </#macro>        <@greet person="Fred"/> and <@greet person="Bob"/>    </p>    <h2>多個參數時,可以設定預設值</h2>    <p>        <#macro greet person color="black">            <font size="+2" color="${color}">Hello ${person}!</font>        </#macro>        <@greet person="Fred"/> and <@greet person="Bob" color="red"/>    </p>

輸出:

4.1.4 嵌套內容

自訂指令可以嵌套內容,和預定義指令相似:<#if ...>nested content</#if>。比如,下面這個例子中是建立了一個可以為嵌套的內容畫出邊框;

<#macro border>    <table border=4 cellspacing=0 cellpadding=4>        <tr>            <td>                <#nested>            </td>        </tr>    </table></#macro>

<#nested>標籤執行位於開始和結束標籤之間的模板代碼塊,例如:

<@border>The bordered text</@border>

輸出:

<table border=4 cellspacing=0 cellpadding=4>    <tr>        <td>            The bordered text        </td>    </tr></table>

<#nested>指令可以被執行多次;

<#macro do_thrice>    <#nested>    <#nested>    <#nested></#macro>

使用時:

<@do_thrice>anything</@do_trice>

輸出:

anythinganythinganything

如果不使用nested指令,那麼嵌套的內容就會被執行,如果不小心寫成這樣:

<@greet person="Joe">    Anything.</@greet>

輸出是:

<font size="+2">Hello Joe!</font>

嵌套的內容被忽略了,因為greet沒有使用nested指令;

嵌套內容可以是其他FTL指令,包含其他自訂指令也是可以的。

<@border>    <ul>        <@do_thrice>            <li><@greet person="Joe"></li>        </@do_thrice>    </ul></@border>

在嵌套的內容中,宏的局部變數是不可見的;

<#macro repeat count>    <#local y="test">    <#list 1..count as x>        ${y} ${count}/${x} : <#nested>    </#list></#macro><@repeat count=3>${y!"?"} ${x!"?"} ${count!"?"}</@repeat>

將會輸出:

test 3/1: ? ? ?test 3/2: ? ? ?test 3/3: ? ? ?

不同的局部變數的設定是為每個宏自己調用的,所以不會導致混亂;

<#macro test foo>${foo} (<#nested>) ${foo}</#macro><@test foo="A"><@test foo="B"><@test foo="C"/></@test></@test>

輸出:

A (B (C () C) B) A
4.1.5 宏與迴圈變數

迴圈變數的名字是已經給定了,變數值的設定由指令本身完成。

<#macro do_thrice>    <#nested 1>    <#nested 2>    <#nested 3></#macro><p>    <#--自訂迴圈變數需要用;代替as-->    <@do_thrice ; x>        do_something : ${x}    </@do_thrice></p>

輸出:

do_something : 1 do_something : 2 do_something : 3 

例子:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/nested.ftl

<h3>宏與迴圈變數</h3><#macro do_thrice>    <#nested 1>    <#nested 2>    <#nested 3></#macro><p>    <#--自訂迴圈變數需要用;代替as-->    <@do_thrice ; x>        do_something : ${x}    </@do_thrice></p>

一個宏可以使用多個迴圈變數(變數的順序是很重要的):

<#macro repeat count>    <#list 1..count as x>        <#nested x, x/2, x==count>    </#list></#macro>

使用的時候:

<@repeat count=4 ; c, halfc, last>    ${c}.${halfc}<#if last> Last!</#if></@repeat>

那麼將會輸出:

\1. 0.5\2. 1\3. 1.5\4. 2 Last!

例子:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/nested.ftl

    <h3>一個宏可以使用多個迴圈變數</h3>    <#macro repeat count>        <#list 1..count as x>            <#nested x, x/2, x==count><br>        </#list>    </#macro>    <p>        <@repeat count=4 ; c, half, last>            ${c}. ${half} <#if last> Last!</#if>        </@repeat>    </p>

如果分號後指定的變數少了或多了,多出的會忽略掉;

    @repeat count=4 ; c, half>        ${c}. ${half}    </@repeat>
4.1.6 自訂指令和宏進階

你也可以在FTL中定義方法,參見function指令;

也許你對命名空間感興趣。命名空間可以協助你組織和重用你經常使用的宏;4.2 在模板中定義變數

可以訪問一個在模板裡定義的變數,就像是訪問資料模型根上的變數一樣。這個變數比定義在資料模型中的同名參數具有更高的優先順序。如果你恰巧定義了一個名為“foo”的變數,而在資料模型中也有一個名為“foo”的變數,那麼模板中的變數就會將資料模型根上的變數隱藏(而不是覆蓋!)。

在模板中可以定義三種類型的變數:

  • 簡單變數:它能從模板中的任何位置訪問,或者從使用include指令引入的模板訪問。可以使用assignmacro指令來建立或替換這些變數。
  • 局部變數:它們只能被設定在宏定義體內,而且只在宏內可見。一個局部變數的生命週期只是宏的調用過程。可以使用local來建立或替換局部變數。
  • 迴圈變數:迴圈變數是由指令(如list)自動建立的,而且它們只在指令的開始和結束標記內有效。宏的參數是局部變數而不是迴圈變數。

使用assign建立和替換變數;

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/variable.ftl

    <h3>簡單變數</h3>    <p>        <#assign x=1> <#--建立變數x-->        ${x}<br>        <#assign x=x+3> <#--替換變數x-->        ${x}    </p>

輸出:

簡單變數14 

局部變數也會隱藏(而不是)同名的簡單變數。迴圈變數也會隱藏(不是覆蓋)同名的局部變數和簡單變數。

執行個體:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/variable.ftl

    <#macro test>        2. ${x}<br>        <#local x="local">        3. ${x}<br>        <#list ["loop"] as x>            4. ${x}<br>        </#list>        5. ${x}<br>    </#macro>    <p>        <#assign x="plain">        1. ${x}<br>        <@test/>        6. ${x}<br>        <#list ["loop"] as x>            7. ${x}<br>            <#assign x="plain2"> <#--在這裡替換了簡單變數x-->            8. ${x}<br>        </#list>        9. ${x}    </p>

輸出:

1. plain2. plain3. local4. loop5. local6. plain7. loop8. loop9. plain2

內部迴圈可以隱藏外部迴圈的變數;

執行個體:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/variable.ftl

        <#list ["loop 1"] as x>            ${x}<br>            <#list ["loop 2"] as x>                ${x}<br>                <#list ["loop 3"] as x>                    ${x}<br>                </#list>                ${x}<br>            </#list>            ${x}<br>        </#list>

輸出:

loop 1loop 2loop 3loop 2loop 1

有時發生一個變數隱藏資料模型中的同名變數,但是如果想訪問資料模型中的變數,就可以使用特殊變數globals

執行個體:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/variable.ftl

        <#assign user="Cindy">        ${user}, ${.globals.user}   

/FreeMarker-hello-web/src/main/java/org/yejq/fre/service/Exercises.java

    public void testVariable(Model model){        model.addAttribute("user", "lucy");    }

測試:http://localhost/test/4/variable/testVariable,輸出結果:

Cindy, lucy
4.3 命名空間4.3.1 簡介

如果想建立可以重複使用的宏、函數和其他變數的集合,通常用術語來說就是引用library庫,使用命名空間是必然的;4.3.2 建立一個庫

執行個體:/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/lib/my_test.ftl

<#macro copyright date>    <p>Copyright (C) ${date} Julia Smith. All rights reserved.</p></#macro><#assign mail="[email protected]">

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/namespace.ftl

    <h3>使用import匯入</h3>    <p>        <#import "../lib/my_test.ftl" as my>        <@my.copyright date="2014-2016"/>        ${my.mail}    </p>

輸出:

使用import匯入Copyright (C) 2014-2016 Julia Smith. All rights reserved.[email protected] 

測試不同的命名空間;

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/lib/my_test.ftl

<#macro copyright date>    <p>Copyright (C) ${date} Julia Smith. All rights reserved.    <br>Mail: ${mail}       </p></#macro><#assign mail="[email protected]">

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/namespace.ftl

    <h3>示範不同的命名空間</h3>    <p>        <#import "../lib/my_test.ftl" as my>        <#assign mail="[email protected]">        <@my.copyright date="2014-2016"/>        ${my.mail}<br>        ${mail}    </p>

測試:http://localhost/test/4/namespace/null4.3.3 在引入的命名空間上編寫變數

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/namespace.ftl

        <#import "../lib/my_test.ftl" as my>        ${my.mail}<br>        <#assign mail="[email protected]" in my>        ${my.mail}

http://localhost/test/4/namespace/null,輸出:

[email protected][email protected] 
4.3.4 命名空間和資料模型

資料模型中的變數在任何位置都是可見的。如果在資料模型中有一個名為user的變數,那麼lib/my_test.ftl也能訪問TA。

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/lib/my_test.ftl

<#macro copyright date>    <p>Copyright (C) ${date} ${user} Julia Smith. All rights reserved.    <br>Mail: ${mail}       </p></#macro><#assign mail="${user}@acme.com">

/FreeMarker-hello-web/src/main/java/org/yejq/fre/service/Exercises.java

    public void testNamespace(Model model){        model.addAttribute("user", "lucy");    }

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/namespace.ftl

    <h3>資料模型中的變數在任何位置都是可見的</h3>    <p>        <#import "../lib/my_test.ftl" as my>        <@my.copyright date="2014-2015"/>    </p>

測試:http://localhost/test/4/namespace/testNamespace?11,輸出結果:

Copyright (C) 2014-2015 lucy Julia Smith. All rights reserved. Mail: [email protected] 
4.3.5 命名空間的生命週期

命名空間由使用的import指令中所寫的路徑來識別。如果想多次import這個路徑,那麼只會為第一次的import引用建立命名空間執行模板。後邊相同的路徑的import只是建立一個雜湊表當做訪問相同命名空間的“門”。

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/namespace.ftl

    <h3>命名空間的聲明周期</h3>    <p>        <#import "/lib/my_test.ftl" as my>        <#import "/lib/my_test.ftl" as foo>        <#import "/lib/my_test.ftl" as bar>        <#--只會在第一次建立命名空間執行模板,之後相同路徑的import只是建立雜湊表當做訪問相同命名空間的"門"-->        ${my.mail}, ${foo.mail}, ${bar.mail}<br>        <#assign mail="[email protected]" in my>        ${my.mail}, ${foo.mail}, ${bar.mail}<br>        <#--其中一個命名空間的值修改了,所有都相應修改,就像java裡邊的對象引用修改一樣-->        <#assign mail="[email protected]" in foo>        ${my.mail}, ${foo.mail}, ${bar.mail}    </p>

訪問:http://localhost/test/4/namespace/null,輸出:

命名空間的聲明周期[email protected], [email protected], [email protected][email protected], [email protected], [email protected][email protected], [email protected], [email protected] 

還要注意命名空間是不分層次的,它們相互之間是獨立存在的。那麼,如果在命名空間N1中import命名空N2,那N2也不在N1中,N1隻是通過雜湊表訪問N2。這和主命名空間中importN2,然後直接存取命名空間N2是一樣的過程。

每一次模板的執行過程,它都有一個私人的命名空間的集合。每一次模板執行工作都是一個分離且有序的過程,它們僅僅存在一段很短的時間,同時頁面用以呈現內容,然後就和所有填充過的命名空間一起消失了。4.3.6 為他人編寫庫

http://freemarker.org/libraries.html

標準庫路徑的格式:

/lib/yourcompany.com/your_library.ftl

如果你的公司的首頁是www.example.com,那麼;

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

一個重要的規則是路徑不應該包含大寫字母,winForm改成win_form;4.4 空白處理4.4.1 簡介

來看看這個模板;

按照Freemarker規則輸出後是:

這麼多多餘的空白是很令人頭疼,而且增加處理後的HTML檔案大小也是沒必要的;

FreeMarker提供了以下工具來處理這個問題:

  • 忽略某些檔案的空白的工具(解析階段空白就被移除了)
    • 剝離空白:這個特性會自動忽略FTL標籤周圍的空白。這個特性可以通過模板來隨時使用和禁用;
    • 微調指令:t, rtlt,使用這些指令可以明確告訴FreeMarker去忽略某些空白;
    • FTL參數strip_text:這將從模板中刪除所有頂級文本。對模板來說很有用,它包含某些定義的宏,因為它可以移除宏定義和其他頂級指令中的分行符號,這樣可以提高模板的可讀性;
  • 從輸出移除空白的工具(移除臨近的空白)
    • compress指令
4.4.2 剝離空白

它會自動忽略兩種典型的空白:

  • 縮排空白和行末尾的尾部空白;如果這行上包含<#if ...>x,那麼空白不會忽略,因為x不是標籤。而一行上有<#if ...> <#list ...>,這樣也不會忽略空白,因為標籤之間的空格是嵌入空白;
  • 加在這些指令之間的空白會被忽略:macro,function,assign,global,local,ftl,import;

使用剝離空白之後,上面的例子輸出是:

剝離空白功能可以在ftl指令在模板中開啟或關閉。預設開啟。開啟剝離空白不會降低模板執行的效率,剝離空白的操作在模板載入時就已經完成了。

剝離空白可以為單獨的一行關閉,就是使用nt指令;4.4.3 使用compress指令

和剝離空白相反,這個工作是直接基於生產的輸出內容,而不是對模板進行的。它會強勢地移除縮排,空行和重複的空格/定位字元;

對於下邊這段代碼:

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/compress.ftl

    <h2>使用compress指令,在輸出的內容中移除縮排,空行和空格/定位字元</h2>    <p>        <#compress>            <#assign users = [{"name":"Joe", "hidden":false},                            {"name":"James Bond", "hidden":true},                            {"name":"Julia", "hidden":false}]>            list of users:<br>            <#list users as user>                <#if !user.hidden>                    - ${user.name}<br>                </#if>            </#list>        </#compress>    </p>

輸出:

        <h2>使用compress指令,在輸出的內容中移除縮排,空行和空格/定位字元</h2>    <p>        list of users:<br>- Joe<br>- Julia<br> </p>

由於向下相容性,名稱為compress的使用者自訂指令是存在的,有個single_line的屬性,如果設定為true,那麼會移除其中的分行符號;

    <h3>@compress的屬性single_line</h3>    <p>        <@compress single_line=true>            <#assign users = [{"name":"Joe", "hidden":false},                            {"name":"James Bond", "hidden":true},                            {"name":"Julia", "hidden":false}]>            list of users:<br>            <#list users as user>                <#if !user.hidden>                    - ${user.name}<br>                </#if>            </#list>        </@compress>    </p>

貌似不起作用,反而#compress是single_line;4.5 替換(方括弧)文法

版本2.3.4之後才有;

在指令和注釋中使用[]代替<>

[#list ...]...[/list][@mymacro .../][#-- the comment --]

為了使用這種文法從而代替預設文法,那麼就需要用[#ftl]來開始模板。

/FreeMarker-hello-web/src/main/webapp/WEB-INF/ftl/4/ftl.ftl

[#ftl]<!doctype html><html lang="en"><head>    <meta charset="UTF-8" />    <title>Document</title></head><body>    <h3>替換文法</h3>    <p>        [#assign users = [{"name":"Joe", "hidden":false},                            {"name":"James Bond", "hidden":true},                            {"name":"Julia", "hidden":false}]]        list of users:<br>        [#list users as user]            [#if !user.hidden]                - ${user.name}<br>            [/#if]        [/#list]    </p></body></html>

測試:http://localhost/test/4/ftl/null

  項目

  1. P1:https://github.com/yejq/FreeMarker-hello-java.git。
  2. P2:https://github.com/yejq/FreeMarker-hello-web.git

FreeMarker筆記 第四章 其它

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.