Freemarker進階(二)

上接Freemarker20分鐘入門Demo(一)

2.1import指令

該指令用於導入FreeMarker模板中的所有變量,並將該變量放置在指定的Map對象中,import指令的語法格式如下: 
<#import “/lib/common.ftl” as xxx> 
上面的代碼將導入/lib/common.ftl模板文件中的所有變量,交將這些變量放置在一個名爲xxx的Map對象中.

 

2.2 macro的使用

這個可以用來實現自定義指令,一般用來做公共組件,我們稱之爲宏

 

2.3macro與import組合實現下拉列表模板組件

2.3.1需求說明

很多網站都有會員等級,這裏我們假設有三個等級,【金牌會員,銀牌會員,普通會員】,這只是顯示的text,真正存儲會員等級字段應該是一個字符編碼,比如數字或一個字符串,我們成爲編碼cd。

現在我們使用macro與import組合實現下拉列表模板組件,並會員等級實現下拉列表。這種統一的模板組件對於開發效率來說是非常有必要的。

2.3.1下拉列表宏構建

新建一個_custom_macros.ftl文件,內容如下

<#-- 下拉框:mode:""全部,1請選擇 -->
<#macro select id  name="" value="" mode="" class="drop" style="width:100px" disabled="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
<select id=${id} name=${localName} class=${class} style=${style} panelHeight=":auto" ${disabled}>
    <#if mode == "">
        <option value="">-- 全部 --</option>
    <#elseif mode == "1">
        <option value="">-- 請選擇 --</option>
    <#else>
    </#if>
    <#if codeList?? && codeList?size &gt; 0>
        <#list codeList as code>
            <option value="${code.codeCd}" <#if code.codeCd == value> selected </#if>>${code.codeText!''}</option>
        </#list>
    </#if>
</select>
</#macro>

說明:

(1)<#macro select id  name="" value="" mode="" class="drop" style="width:100px" disabled="">

定義了這個宏接受的參數列表並對某些參數進行了初始化,其中,mode爲控制下拉列表默認顯示樣式,邏輯一眼就能看出來,就不多說了。

(2)<#macro 後跟的第一個字符會被認爲是該宏的別名,調用的時候會根據這個別名調用,這裏起名爲select。

(2)我們這裏寫死了,取參數codeList中的值作爲下拉列表的內容填充,真正這個地方的數據填充從什麼地方獲取,我們稍後再說,這裏先寫死。

2.3.2codeList數據準備

(1)在項目中我們根據會員的codecd及codetest設計一個pojo名爲code

/**
 * @author suyouliang
 * @version v1.0 2018年08月21日 18:00
 * 這是一個字典對象
 */

public class Code {
    private String codeCd;
    private String codeText;

    public String getCodeCd() {
        return codeCd;
    }

    public void setCodeCd(String codeCd) {
        this.codeCd = codeCd;
    }

    public String getCodeText() {
        return codeText;
    }

    public void setCodeText(String codeText) {
        this.codeText = codeText;
    }
}

(2)數據準備

import freemarker.template.Configuration;
import freemarker.template.Template;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author suyouliang
 * @version v1.0 2018年08月21日 17:17
 */
public class FreemarkerDemo {
    public static void main(String[] args) throws Exception {
        //1.創建配置類
        Configuration configuration=new Configuration(Configuration.getVersion());
        //2.設置模板所在的目錄
        configuration.setDirectoryForTemplateLoading(new File("D:\\freemarkerdemo"));
        //3.設置字符集
        configuration.setDefaultEncoding("utf-8");
        //4.加載模板
        Template template = configuration.getTemplate("test.ftl");
        //5.創建數據模型
        Map map=new HashMap();
        initCodeList(map);
        //6.創建Writer對象
        Writer out =new FileWriter(new File("D:\\freemarkerdemo\\test.html"));
        //7.輸出
        template.process(map, out);
        //8.關閉Writer對象
        out.close();
    }

    private static void initCodeList(Map map) {
        List<Code> codeList = new ArrayList();
        Code code1 = new Code();
        Code code2 = new Code();
        Code code3 = new Code();
        code1.setCodeCd("1");
        code1.setCodeText("普通會員");
        code2.setCodeCd("2");
        code2.setCodeText("銀牌會員");
        code3.setCodeCd("3");
        code3.setCodeText("黃金會員");
        codeList.add(code1);
        codeList.add(code2);
        codeList.add(code3);
        map.put("codeList", codeList);

    }
}

這樣,我們就在模板引擎中放入了codeList對象。

2.3.3在頁面中使用宏

<#import "_custom_macros.ftl" as cont>
<html>
<head xmlns="http://www.w3.org/1999/html">
    <meta charset="utf-8">
    <title>Freemarker入門小DEMO </title>
</head>
<body>
<#--我是一個註釋,我不會有任何輸出  -->
<!--我也是個註釋,但是我會在生成的文件中輸出-->
</br>

<p>多選框:<@cont.select id="member_grade"  value="2"/></p>

</body></html>

說明:

(1)首先先通過<#import >指令導入我們定義好的下拉列表的宏,並起別名爲cont方便使用

(2)通過<@cont.select>語法調用宏  其中,cont是我們自己起的別名,@+別名是規定的語法,select就是我們自己在宏中定義的宏的名稱。

這裏我們初始化了宏中定義的id,以及value,根據2.3.1中的邏輯,,這裏其實是定義了下拉列表的value和默認選項。由於沒有定義mode的值,在value爲空的時候,默認顯示的方式是“--全部--”,當指定mode值爲1是,就可以更改爲“--請選擇--”,宏中邏輯很容易看出來。

我們運行main方法,生成的test.html如下:

<html>
<head xmlns="http://www.w3.org/1999/html">
    <meta charset="utf-8">
    <title>Freemarker入門小DEMO </title>
</head>
<body>
<!--我也是個註釋,但是我會在生成的文件中輸出-->
</br>

<p>多選框:<select id=member_grade name=member_grade class=drop style=width:100px panelHeight=":auto" >
        <option value="">-- 全部 --</option>
            <option value="1" >普通會員</option>
            <option value="2"  selected >銀牌會員</option>
            <option value="3" >黃金會員</option>
</select>
</p>

</body></html>

在網頁中打開效果:

默認就是銀牌會員。

2.3.4宏功能擴展

我們可以把日常用的,單選,多選,日曆甚至分頁宏加入我們的宏邏輯中

<#-- 下拉框:mode:""全部,1請選擇 -->
<#macro select id  name="" value="" mode="" class="drop" style="width:100px" disabled="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
<select id=${id} name=${localName} class=${class} style=${style} panelHeight="auto" ${disabled}>
    <#if mode == "">
        <option value="">-- 全部 --</option>
    <#elseif mode == "1">
        <option value="">-- 請選擇 --</option>
    <#else>

    </#if>
    <#if codeList?? && codeList?size &gt; 0>
        <#list codeList as code>
            <option value="${code.codeCd}" <#if code.codeCd == value> selected </#if>>${code.codeText!''}</option>
        </#list>
    </#if>
</select>
</#macro>

<#-- 單選鈕  -->
<#macro radio id name="" value=""  class="rad" isDefault = "true" disabled="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
    <#if codeList?? && codeList?size &gt; 0>
        <#list codeList as code>
        <input type="radio" id="${id}" name="${localName}" class="${class}" value="${code.codeCd}" <#if code.codeCd == value  || (isDefault == 'true' && value == '' && code_index == 0)> checked </#if>  ${disabled}/> ${code.codeText}
        </#list>
    </#if>
</#macro>


<#-- 複選鈕  -->
<#macro checkbox id name="" value=[] >
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
    <#list codeList as code>
        <#local checked=""/>
        <#list value as val>
            <#if val == code.codeCd>
                <#local checked="checked"/>
                <#break>
            </#if>
        </#list>
    <input type="checkbox" id="${id}" name="${localName}" value="${code.codeCd}" class="chk" ${checked} /> ${code.codeText}
    </#list>
</#macro>

<#-- 日曆控件  -->
<#macro calendar id name="" value="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
<input type="text" id="${id}" name="${localName}" value="${value}" class="Wdate" />
</#macro>

   2.4freemarker的宏在實際開發中的應用場景

以上提到,codeList是我們定義死的,這個顯然是不合理的,那麼以上例子在實際開發中的應用場景到底是什麼樣的呢。

2.4.1字典應用場景

企業開發中字典被廣泛應用,一般主要是一個codeCd和一個codeText,我們在給這一組字典起名爲codeNamecode,將該字典封裝爲到叫code的pojo。字典的使用會使我們相關的顯示更加靈活,就比如上面舉的會員等級text,有一天老闆說:“叫金牌會員,銀牌會員太土了,改叫尊享會員和至尊會員吧”   你:“啊啊?” 這麼多頁面,相信你會改到懷疑人生。

在使用字典的項目中,使用以上的宏將非常有意義,他可以確保所有的顯示都是引用字典中定義的,一旦需要修改,只需要更改字典中的text即可。

我們可以定義一個CodeManager用來管理字典表,這個類啓動時加載,加載時查詢數據庫中的字典表並裝到內存(或外部緩存)中(爛尾文章,前面還是很實用的)

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章