FreeMarker自定义TemplateDirectiveModel
【参考:http://blog.csdn.net/fangzhangsc2006/article/details/8687371】
在采用FreeMarker做前台视图模板的情况下,我们可以通过<#include>标签和自定义宏来解决很多重复性工作。
一个简单的FreeMarker宏:
- <#macro sayHello name="">
- hello ${name}
- </#macro>
然后通过如下的形式调用:
- <@sayHello name="shannon" />
不过这种在模板页中定义的宏能力有限。【1】假设,我们很多页面都要输出一个热门排行框,而排行数据需要从controller层动态获取,我们可以用这种宏来完成所有的展示工作,但前提是相应的controller和接口中层需要预先将这些排行数据放到model中去,因此对于后端来说这也是一个重复性的工作。那么有没有一种方式可以让后端也脱离这种重复工作呢?答案是肯定的,这也是写这篇博客的目的。
在一个偶然的机会发现jeecms项目中用到了这种方式,于是借鉴了一番。
FreeMarker不仅可以在前端的模板页中定义宏,还可以通过扩展其接口在后端实现宏,这有什么好处呢?这种方式就好比让你的模板页具备了从前端再次回到后端的能力。这样我们就能很好的解决【1】处的假设,我们无需在各个controller的各个接口中去重复的向model中添加所需的排行数据,而是当FreeMarker渲染模板页时遇到相应的宏它可以回到后端去调用相应的方法取到所需的数据。例子如下:
- import freemarker.core.Environment;
- import freemarker.template.ObjectWrapper;
- import freemarker.template.TemplateDirectiveModel;
- /**
- * FreeMarker自定义宏
- * 获取App下载排行列表
- * 参数包括 length(列表长度) mtypeCode(主类型代码) typeCode(小类型代码) rankMode(排行模式1、2、3)
- * @author shannon
- *
- */
- public class FMAppRankDirective implements TemplateDirectiveModel {
- @Resource(name = "appRankService")
- private AppRankService appRankService;
- @SuppressWarnings("unchecked")
- @Override
- public void execute(Environment env, Map params, TemplateModel[] loopVars,
- TemplateDirectiveBody body) throws TemplateException, IOException {
- //DirectiveUtils是借用jeecms项目中的工具类,主要是因为它集成了一些异常处理功能,
- //其实完全可以不用它,params是个Map,自己通过key取值就可以了,做一下空值判断
- Integer length = DirectiveUtils.getInt("length", params);
- Integer mtypeCode = DirectiveUtils.getInt("mtypeCode", params);
- Integer typeCode = DirectiveUtils.getInt("typeCode", params);
- Integer rankMode = DirectiveUtils.getInt("rankMode", params);
- ArrayList<App> rankList = appRankService.getRankList(length, mtypeCode, typeCode, rankMode);
- env.setVariable("appRankList", ObjectWrapper.DEFAULT_WRAPPER.wrap(rankList));
- if (body != null) {
- body.render(env.getOut());
- }
- }
- }
通过实现FreeMarker的TemplateDirectiveModel就在后端实现了一个自定义的宏,这个宏的功能很简单,只是根据给定的参数将排行数据“appRankList”放到model中去,然后模板页中就可以使用这个变量了。
FreeMarker的配置参数中需要将这个宏加入进去。
- <bean id="appRankDirective" class="com.shannon.example.rank.util.FMAppRankDirective" />
- <bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
- ……其他配置略……
- <property name="freemarkerVariables">
- <map>
- ……其他配置略……
- <entry key="appRankDirective" value-ref="appRankDirective"/>
- </map>
- </property>
- </bean>
在模板页中使用:
- <#-- 应用下载排行框,title为该框的标题,length为排行列表长度,mtypeCode为主类型代码,typeCode为小类型代码,rankMode为排行方式
- 1为总下载量,2为月下载量,3为昨日增长下载量
- -->
- <#macro appRankBox title="" length=10 mtypeCode=1 typeCode=-1 rankMode=1>
- <@appRankDirective length=length mtypeCode=mtypeCode typeCode=typeCode rankMode=rankMode />
- <h3 class="box-title">${title}</h3>
- <div class="box">
- <ul class="row-list">
- <#list appRankList as item>
- ……详细输出内容略……
- </#list>
- </ul>
- </div>
- </#macro>
这里我在模板页中又定义了一个宏,负责内容及样式的输出,因为模板页中的宏比较直观,让后端的宏只负责拿数据。其他页面直接使用“appRankBox”就可以了,然后由它来调用后端的“appRankDirective”宏来拿数据。
这样,controller就从重复工作中脱身了。
FreeMarker自定义TemplateDirectiveModel的更多相关文章
- 关于FreeMarker自定义TemplateDirectiveModel
[转载来源:http://zwllxs.iteye.com/blog/2036826] java代码如下: import freemarker.core.Environment; import fre ...
- FreeMarker 自定义 TemplateDirectiveModel(二)
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不 ...
- FreeMarker 自定义 TemplateDirectiveModel(一)
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不 ...
- 基于SSM3框架FreeMarker自定义指令(标签)实现
通过之前的Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解系列文章,我们已经成功的整合到了一起,这次大象将在此基础上对框架中的FreeMarker模板 ...
- freemarker自定义标签(与java合用)
自定义类继承FreemarkerManager类,重写protected Configuration createConfiguration(ServletContext servletContext ...
- OneBlog开源博客-详细介绍如何实现freemarker自定义标签
前言 OneBlog中使用到了springboot + freemarker的技术,同时项目里多个controller中都需要查询一个公有的数据集合,一般做法是直接在每个controller的方法中通 ...
- freemarker 自定义标签
1.编写标签类 package com.pccw.business.fnd.common.filegen; import java.io.IOException; import java.io.Wri ...
- freemarker自定义标签报错(六)
freemarker自定义标签 1.错误描述 freemarker.core.ParseException: Encountered "\"\u4f60\u597d\uff01\& ...
- freemarker自定义标签报错(五)
freemarker自定义标签 1.错误描述 六月 05, 2014 11:40:49 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严 ...
随机推荐
- Java进阶之自动拆箱与自动装箱
序. java基本类型介绍 java中,基本数据类型一共有8种,详细信息如下表: 类型 大小 范围 默认值 byte 8 -128 - 127 0 short 16 -32768 - 32768 0 ...
- Springboot-mongodb MongoRepository接口 save方法 详解
问题: 我们都知道 mongodb 有两种添加数据的方式 一种 就是 save 方法 另外一种 insert 方法 这里两个方法 唯一的区别就是 insert:当主键"_id&qu ...
- centos mysql忘记密码
1.停止mysql 服务:service mysqld stop; 2.vim命令打开mysql配置文件my.cnf(位置一般为:/etc/my.cnf) 3.在mysqld进程配置文件中添加skip ...
- Mac OSX 如何在命令行中生成 md5、sha1、sha256 校验和
计算 MD5 校验和 md5 /tmp/hello.txt 计算 SHA-1 校验和 shasum -a 1 /tmp/hello.txt 计算 SHA-256 校验和 shasum -a 256 / ...
- Kafka消息topic分区
kafka是为分布式环境设计的,因此如果日志文件,其实也可以理解成消息数据库,放在同一个地方,那么必然会带来可用性的下降,一挂全挂,如果全量拷贝到所有的机器上,那么数据又存在过多的冗余,而且由于每 ...
- Java BigInteger 与C# BigInteger之间的问题
最近接到一个Java代码转C#代码的项目.本来就两个函数看起来很简单的,后来折腾了一天,终于完美收官. 碰到的第一个问题是:java的BigInteger构造函数里面BigInteger(string ...
- flask学习(五):使用配置文件
1. 新建一个config.py文件 2. 在主app文件中导入这个文件,并且配置到app中,示例代码如下: import config app.config.from_object(config) ...
- RocketMQ学习分享
消息队列的流派 什么是 MQ Message Queue(MQ),消息队列中间件.很多人都说:MQ 通过将消息的发送和接收分离来实现应用程序的异步和解偶,这个给人的直觉是——MQ 是异步的,用来解耦的 ...
- C++调用Python脚本中的函数
1.环境配置 安装完python后,把python的include和lib拷贝到自己的工程目录下 然后在工程中包括进去 2.例子 先写一个python的测试脚本,如下 这个脚本里面定义了两个函数Hel ...
- Linux内建命令和外部命令
Linux命令有内部命令(内建命令)和外部命令之分,内部命令和外部命令功能基本相同,但也有些细微差别. [内部命令 vs. 外部命令] (1)内部命令实际上是shell程序的一部分,其中包含的是一些比 ...