Freemarker入门(二)
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
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 > 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的显示
可以看到,我们设置的value=2的属性及disabled属性生效了。
2.3.6Demo目录
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 > 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 > 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页面的任何地方访问,从而就达到我们的目的。具体的实现到下次写(三)的时候在说吧,回家吃饭,饿!!!!
上一篇: vue.js(4)--字符串跑马灯
下一篇: 吃煮苹果消化系统会越来越强哦