FreeMarker 自定义 TemplateDirectiveModel(一)
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。一、Freemarker 的介绍 Freemarker 是一款模板引擎,是一种基于模版生成静态文件的通用 工具,它是为 java 程序员提供的一个开发包,或者说是一个类库,它不是面向最终用户的,而是为程序员提供了一款可以嵌入他们开发产品的应用程序。 Freemarker 是使用纯 java 编写的,为了提高页面的访问速度,需要把页面静态化, 那么 Freemarker 就是被用来生成 html 页面。 到目前为止,Freemarker 使用越来越广泛,不光光只是它强大的生成技术,而且它能够与 spring 进行很好的集成。 现在开始一层层揭开它的神秘面纱。。二、Freemarker 的准备条件 freemarker.2.3.16.jar三、Freemarker 生成静态页面的原理 Freemarker 生成静态页面,首先需要使用自己定义的模板页面,这个模板页面可以是最最普通的 html,也可以是嵌套 freemarker 中的 取值表达式, 标签或者自定义标签等等,然后后台读取这个模板页面,解析其中的标签完成相对应的操作, 然后采用键值对的方式传递参数替换模板中的的取值表达式,做完之后 根据配置的路径生成一个新的 html 页面, 以达到静态化访问的目的。四、Freemarker 提供的标签 Freemarker 提供了很多有用 常用的标签,Freemarker 标签都是 <# 标签名称> 这样子命名的,${value} 表示输出变量名的内容 ,具体如下:list:该标签主要是进行迭代服务器端传递过来的 List 集合,比如: <#list nameList as names> ${names} </#list> name 是 list 循环的时候取的一个循环变量,freemarker 在解析 list 标签的时候,等价于:for (String names : nameList) {System.out.println(names);} if: 该标签主要是做 if 判断用的,比如: <#if (names=="陈靖仇")>他的武器是: 十五~~ </#if> 这个是条件判断标签,要注意的是条件等式必须用括号括起来, 等价于:if(names.equals("陈靖仇")){System.out.println("他的武器是: 十五~~");} include:该标签用于导入文件用的。 <#include "include.html"/> 这个导入标签非常好用,特别是页面的重用。另外在静态文件中可以使用 ${} 获取值,取值方式和 el 表达式一样,非常方便。 下面举个例子(static.html):<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body>描述:${description} <br/> 集合大小:${nameList?size} <br/> 迭代list集合: <br/> <#list nameList as names> 这是第${names_index+1}个人,叫做:<label style="color:red">${names}</label> if判断: <br/> <#if (names=="陈靖仇")>他的武器是: 十五~~ <#elseif (names=="宇文拓")> <#--注意这里没有返回而是在最后面--> 他的武器是: 轩辕剑~· <#else> 她的绝招是:蛊毒~~ </#if> <br/> </#list> 迭代map集合: <br/> <#list weaponMap?keys as key> key--->${key}<br/> value----->${weaponMap[key]!("null")} <#-- fremarker 不支持null, 可以用! 来代替为空的值。 其实也可以给一个默认值 value-----${weaponMap[key]?default("null")} 还可以 在输出前判断是否为null <#if weaponMap[key]??></#if>都可以 --><br/> </#list> include导入文件: <br/> <#include "include.html"/></body> </html> 实际代码:package com.chenghui.test;import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.Template; import freemarker.template.TemplateException;public class CreateHtml {public static void main(String[] args) {try {//创建一个合适的Configration对象Configuration configuration = new Configuration();configuration.setDirectoryForTemplateLoading(new File("D:\\project\\webProject\\WebContent\\WEB-INF\\template"));configuration.setObjectWrapper(new DefaultObjectWrapper());configuration.setDefaultEncoding("UTF-8"); //这个一定要设置,不然在生成的页面中 会乱码//获取或创建一个模版。Template template = configuration.getTemplate("static.html");Map<String, Object> paramMap = new HashMap<String, Object>();paramMap.put("description", "我正在学习使用Freemarker生成静态文件!");List<String> nameList = new ArrayList<String>();nameList.add("陈靖仇");nameList.add("玉儿");nameList.add("宇文拓");paramMap.put("nameList", nameList);Map<String, Object> weaponMap = new HashMap<String, Object>();weaponMap.put("first", "轩辕剑");weaponMap.put("second", "崆峒印");weaponMap.put("third", "女娲石");weaponMap.put("fourth", "神农鼎");weaponMap.put("fifth", "伏羲琴");weaponMap.put("sixth", "昆仑镜");weaponMap.put("seventh", null);paramMap.put("weaponMap", weaponMap);Writer writer = new OutputStreamWriter(new FileOutputStream("success.html"),"UTF-8");template.process(paramMap, writer);System.out.println("恭喜,生成成功~~");} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();}} } 这样子基本上可以算的上可以简单的去做一点简单的生成了,但是要在实际中去运用,还是差的很远的,因为 freemarker 给的标签完全满足不了我们的需要,这时候就需要自定义标签来完成我们的需求了。。五、Freemarker 自定义标签 Freemarker 自定义标签就是自己写标签,然后自己解析,完全由自己来控制标签的输入输出,极大的为程序员提供了很大的发挥空间。基于步骤: 以前写标签需要在 <后加# ,但是 freemarker 要识别自定义标签需要在后面加上 @,然后后面可以定义一些参数,当程序执行 template.process(paramMap, out);, 就会去解析整个页面的所有的 freemarker 标签。 自定义标签 需要自定义一个类,然后实现 TemplateDirectiveModel,重写 execute 方法,完成获取参数,根据参数 do something 等等。 将自定义标签与解析类绑定在一起需要在 paramMap 中放入该解析类的实例,存放的 key 与自定义标签一致即可。 注意:在自定义标签中,如果标签内什么也没有,开始标签和结束标签绝对不能再同一行,不然会报错 freemarker.log.JDK14LoggerFactory$JDK14Logger error例: static.html 模板<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <#--自定义变量--> <#assign num='hehe'/> ${num} <br/> 自定义标签<@content name="chenghui" age="120">${output}${append}</@content></body> </html> static.html 模板解析类: 参数解释:TemplateDirectiveModel 接口是 freemarker 自定标签或者自定义指令的核心处理接口。通过实现该接口,用户可以自定义标签(指令)进行任意操作, 任意文本写入模板的输出。 该接口中只定义了如下方法,当模板页面遇到用户自定义的标签指令时,该方法会被执行。 public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body) throws TemplateException, IOException;@param env:系统环境变量,通常用它来输出相关内容,如 Writer out = env.getOut();@param params:自定义标签传过来的对象,其 key = 自定义标签的参数名,value 值是 TemplateModel 类型,而 TemplateModel 是一个接口类型,通常我们都使用 TemplateScalarModel 接口来替代它获取一个 String 值,如 TemplateScalarModel.getAsString(); 当然还有其它常用的替代接口,如 TemplateNumberModel 获取 number,TemplateHashModel 等@param loopVars 循环替代变量@param body 用于处理自定义标签中的内容,如 <@myDirective> 将要被处理的内容 /@myDirective;当标签是 <@myDirective /> 格式时,body=nullpackage com.chenghui.test;import static freemarker.template.ObjectWrapper.DEFAULT_WRAPPER;import java.io.IOException; import java.io.Writer; import java.util.Map;import freemarker.core.Environment; import freemarker.template.TemplateDirectiveBody; import freemarker.template.TemplateDirectiveModel; import freemarker.template.TemplateException; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; import freemarker.template.TemplateNumberModel; import freemarker.template.TemplateScalarModel;/*** 自定义标签解析类* @author Administrator**/ public class ContentDirective implements TemplateDirectiveModel{private static final String PARAM_NAME = "name";private static final String PARAM_AGE = "age";@Overridepublic void execute(Environment env, Map params,TemplateModel[] loopVars,TemplateDirectiveBody body) throws TemplateException, IOException {if(body==null){throw new TemplateModelException("null body");}else{String name = getString(PARAM_NAME, params);Integer age = getInt(PARAM_AGE, params);//接收到参数之后可以根据做具体的操作,然后将数据再在页面中显示出来。if(name!=null){env.setVariable("output", DEFAULT_WRAPPER.wrap("从ContentDirective解析类中获得的参数是:"+name+", "));}if(age!=null){env.setVariable("append", DEFAULT_WRAPPER.wrap("年龄:"+age));}Writer out = env.getOut();out.write("从这里输出可以再页面看到具体的内容,就像document.writer写入操作一样。<br/>");body.render(out);/*如果细心的话,会发现页面上是显示out.write()输出的语句,然后再输出output的内容,可见 在body在解析的时候会先把参数放入env中,在页面遇到对应的而来表单时的才会去取值但是,如果该表单时不存在,就会报错, 我觉得这里freemarker没有做好,解析的时候更加会把错误暴露在页面上。可以这样子弥补${output!"null"},始终感觉没有el表达式那样好。*/}}/*** 获取String类型的参数的值* @param paramName* @param paramMap* @return* @throws TemplateModelException*/public static String getString(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{TemplateModel model = paramMap.get(paramName);if(model == null){return null;}if(model instanceof TemplateScalarModel){return ((TemplateScalarModel)model).getAsString();}else if (model instanceof TemplateNumberModel) {return ((TemplateNumberModel)model).getAsNumber().toString();}else{throw new TemplateModelException(paramName);}}/*** * 获得int类型的参数* @param paramName* @param paramMap* @return* @throws TemplateModelException */public static Integer getInt(String paramName, Map<String, TemplateModel> paramMap) throws TemplateModelException{TemplateModel model = paramMap.get(paramName);if(model==null){return null;}if(model instanceof TemplateScalarModel){String str = ((TemplateScalarModel)model).getAsString();try {return Integer.valueOf(str);} catch (NumberFormatException e) {throw new TemplateModelException(paramName);}}else if(model instanceof TemplateNumberModel){return ((TemplateNumberModel)model).getAsNumber().intValue();}else{throw new TemplateModelException(paramName);}} } 然后再前面的实际代码中加上:paramMap.put("content", new ContentDirective()); 这样子基本上可以使用,freemarker 完成自定义标签了,解决一写简单的业务逻辑, 但是在实际的项目中不可能这样子去做,因为还没有和 spring 进行集成使用,每次都需要在解析的时候把解析类的实例放进去。
转载于:https://www.cnblogs.com/Jeely/p/11224370.html
FreeMarker 自定义 TemplateDirectiveModel(一)相关推荐
- freemarker自定义标签(二十一)
一,讲解一 假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术 ...
- Freemarker自定义标签
一. 用macro实现自定义指令,例如: 自定义指令可以使用macro指令来定义. <#macro greet person> <font size ...
- freemarker自定义指令及方法
"一节复一节,千枝攒万叶"竹子每生长一段就会总结一下打个节,今天我也总结一下最近处理的一个小问题,希望我的小节,对各位看官有所帮助. 背景描述: 最近项目做了一个月报功能,由于生产 ...
- FreeMarker自定义标签编写
一.freemarker 实现自定义标签的方法 : 使用 <macro></macro> 宏定定义标签 实现 TemplateDirectiveModel的 execut ...
- freeMarker自定义函数的使用
1. 编写函数 1 package com.freemarker.test; 2 3 import java.text.SimpleDateFormat; 4 import java.util.D ...
- freemarker -自定义指令
自定义指令可以使用,Marco指令来进行定义 宏 是有一个变量名的模板片段,在模板中使用宏作为自定义指令,这样就能供其他页面使用. <#macro greet><font size= ...
- freemarker,自定义指令
一,自定义指令 <#-- 自定义指令 --> <#macro mycommand1>我的第一个自定义指令 </#macro> <#-- 调用自定义带参数的指令 ...
- freemarker程序开发
1.程序开发入门 1.1 创建配置实例 首先,你应该创建一个freemarker.template.Configuration的实例,然后调整它的设置.Configuration实例是存储FreeMa ...
- 全面探索 FreeMarker 模版引擎的扩展性
FreeMarker 模版引擎简介 FreeMarker 是一个采用 Java 开发的模版引擎,是一个基于模版生成文本的通用工具. FreeMarker 被设计用来生成 HTML Web 页面,特别是 ...
最新文章
- 从这篇YouTube论文,剖析强化学习在工业级场景推荐系统中的应用
- php 如何发送json数据格式,Php如何使用curl发送json格式数据实例
- (转)android UI进阶之用ViewPager实现欢迎引导页面
- 15 个 JavaScript Web UI 库 (转)
- STL源码剖析---空间配置器
- python concat去除重复值语句_Python数据处理从零开始----第二章(pandas)④数据合并和处理重复值...
- 安卓动态调试七种武器之离别钩 – Hooking(下)
- 单片机实训简易计算机,单片机简易计算器实验报告.doc
- C++ 函数参数中和区别
- 什么是configmap资源、secret资源(实战)
- labview 判断整数_labview教程——如何判断字符串包含的是数字
- 报错:SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“.
- IIS服务器安全配置[摘]
- Ubuntu无法ping通百度
- 家庭收入支出系统管理c语言,家庭支出管理系统—c语言程序的设计说明.doc
- 开源SWD脱机烧录器-第三章 基于QT的上位机
- 软件著作权审查时间、软件导刊审稿周期、计算机工程与应用审稿周期、计算机技术与发展审稿周期、电子测量与仪器学报审稿周期
- 什么是微型计算机组成原理,SJTU 《微型计算机组成原理》备考题
- Lightroom:移除高 ISO 噪点
- pos系统开发步骤2- 建立数据库和表