欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Freemarker入门(二)

程序员文章站 2022-04-29 20:58:02
...

2.1.import指令

该指令用于导入FreeMarker模板中的所有变量,并将该变量放置在指定的Map对象中,import指令的语法格式如下: 
<#import “/lib/common.ftl” as com> 
上面的代码将导入/lib/common.ftl模板文件中的所有变量,交将这些变量放置在一个名为com的Map对象中.

2.2 macro的使用

这个可以用来实现自定义指令,一般用来做公共组件,我们称macro制作的组件为宏

2.3.1宏的制作

现在我们通过使用macro及import指令组合,实现通用的下拉列表的宏,来简化前端开发。

2.3.2定义一个需求

(1)假设系统中需要有一个会员等级的下拉列表,会员等级显示共三级,【普通会员,银牌会员,金牌会员】-->中文名称-->codeText

(2)对应顺序的存储的编码为,【1,2,3】。-->code的id-->codeCd

(3)这一组下拉列表我们起一个名称叫“member_grade”-->一组code的id-->codeDiv

2.3.3数据准备

(1)根据以上关系,将该下拉列表封装成一个pojo,名为code

/**
 * @author suyouliang
 * @version v1.0 2018年08月21日 18:00
 * 这是一个字典对象
 */

public class Code {
    private String codeDiv;//code组id
    private String codeCd;//code的存储编码(code的id)
    private String codeText;//code的中文名称


    public String getCodeDiv() {
        return codeDiv;
    }

    public void setCodeDiv(String codeDiv) {
        this.codeDiv = codeDiv;
    }
    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;
    }
}

我们构建这一个json方便前端使用,为了防止出错,我们使用fastjson帮助生成json

(2)pom文件引入fastjson相关jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>FreemarkeDemo</groupId>
    <artifactId>com.freemarker.demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.23</version>
    </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.6</version>
        </dependency>
    </dependencies>

</project>

(3)初始化后端数据,新建一个CodeManager用来管理Code数据,并转换为json

import com.alibaba.fastjson.JSONArray;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author suyouliang
 * @version v1.0 2018年08月21日 20:22
 */

public class CodeManager {
    private static Map<String, List<Code>> codeMap;
    static {
        codeMap = new HashMap<String, List<Code>>();
        initCodeList();
    }
    public static void main(String[] args) {

        System.out.println(JSONArray.toJSON(codeMap));

    }
    private static void initCodeList() {
        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);
        codeMap.put("member_grade", codeList);
    }
}

(4)运行main方法获取json

Freemarker入门(二)

2.3.4宏的编写新建_custom_macros.ftl,内容如下

<#assign  text="{'member_grade':[{'codeCd':'1','codeText':'普通会员'},{'codeCd':'2','codeText':'银牌会员'},{'codeCd':'3','codeText':'黄金会员'}]}">
<#assign codeMap=text?eval>
<#-- 下拉框:mode:""全部,1请选择 -->
<#macro select id codeDiv name="" value="" mode="" class=""  disabled="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
<select id=${id} name=${localName} class=${class}  panelHeight="auto" ${disabled}>
    <#if mode == "">
        <option value="">-- 全部 --</option>
    <#elseif mode == "1">
        <option value="">-- 请选择 --</option>
    <#else>

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

说明:

(1)将json数据中的双引号替换为单引号。

(2)<#macro 后面的select即为该宏的名称,此名称在调用的时候会用到,其后的为参数

(3)id参数及name参数:id定义时,将采用id作为select控件的name值,否则使用参数name

(4)codeDiv:指定选用那个Code组

(5)mode:指定无默认选项时,默认显示为“--全部--”还是“--请选择--”

(6)class,style,disabled均为select的原始属性,当然也可以根据需求增加select控件的其他属性。

2.3.5宏的使用

在test.ftl中通过<#import>指令引用宏


<#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" codeDiv="member_grade"  value="2" disabled="disabled"/></p>

</body></html>

(1)cont为自定义的别名,通过<@+别名>的语法调用。

(2)这里设置了value=“2”,即默认显示“银牌会员“”。并且不可点击(disabled属性),下面的结果可以印证。

 

运行FreemarkerDemo的main方法测试一下

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

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
/**
 * @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.创建数据模型
        HashMap<String,List<Code>> codeMap=new HashMap();//这里没有放任何数据
        //6.创建Writer对象
        Writer out =new FileWriter(new File("D:\\freemarkerdemo\\test.html"));
        //7.输出
        template.process(codeMap, out);
        //8.关闭Writer对象
        out.close();
    }
}

生成的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=  panelHeight="auto" disabled>
        <option value="">-- 全部 --</option>
            <option value="1" >普通会员</option>
            <option value="2"  selected >银牌会员</option>
            <option value="3" >黄金会员</option>
</select>
</p>

</body></html>

test.html的显示

Freemarker入门(二)

可以看到,我们设置的value=2的属性及disabled属性生效了。

2.3.6Demo目录

Freemarker入门(二)

2.4宏的扩展

还可以将平时用的单选框,多选框,日历甚至分页栏使用宏完成。

 

<#assign  text="{'member_grade':[{'codeCd':'1','codeText':'普通会员'},{'codeCd':'2','codeText':'银牌会员'},{'codeCd':'3','codeText':'黄金会员'}]}">
<#assign codeMap=text?eval>
<#-- 下拉框:mode:""全部,1请选择 -->
<#macro select id codeDiv 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 codeMap[codeDiv]?? && codeMap[codeDiv]?size &gt; 0>
        <#list codeMap[codeDiv] as code>
            <option value="${code.codeCd}" <#if code.codeCd == value> selected </#if>>${code.codeText!''}</option>
        </#list>
    </#if>
</select>
</#macro>

<#-- 单选钮  -->
<#macro radio id name="" value="" codeDiv="" class="rad" isDefault = "true" disabled="" >
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
    <#if codeMap[codeDiv]?? && codeMap[codeDiv]?size &gt; 0>
        <#list codeMap[codeDiv] 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=[] codeDiv="">
    <#if name == "">
        <#local localName=id/>
    <#else>
        <#local localName=name/>
    </#if>
    <#list codeMap[codeDiv] 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.5宏的使用场景

以上定义的code相信大家都已经看出来了,这就是我们平时项目开发时所用到的字典。使用字典可以定义一个统一的标准,方便后期修改。并且在前后端传参方面非常便利。当定义一个code组的Id后,前端根据这个组id定义去调用,后端根据这个组id的定义去接收,双方可以异步开发,面向接口编程。

以上的codeMap是我写死在前端页面的,实际开发场景中,应该将CodeManager功能增加,让其init方法加载字典表中的所有字典。并开放根据codeDiv查询codeList等方法给后端使用,让他成为一个真正的字段管理者。

然后我们在spring容器加载的时候加载这个CodeManager,这样codeMap就会随之初始化进入我们的内存(使用外部缓存一个道理)。然后我们通过FreeMarker的静态模块加载容器中的CodeManager,让这个类可以在freemarker页面的任何地方访问,从而就达到我们的目的。具体的实现到下次写(三)的时候在说吧,回家吃饭,饿!!!!