【参考:http://blog.csdn.net/fangzhangsc2006/article/details/8687371】

在采用FreeMarker做前台视图模板的情况下,我们可以通过<#include>标签和自定义宏来解决很多重复性工作。

一个简单的FreeMarker宏:

  1. <#macro sayHello name="">
  2. hello ${name}
  3. </#macro>

然后通过如下的形式调用:

  1. <@sayHello name="shannon" />

不过这种在模板页中定义的宏能力有限。【1】假设,我们很多页面都要输出一个热门排行框,而排行数据需要从controller层动态获取,我们可以用这种宏来完成所有的展示工作,但前提是相应的controller和接口中层需要预先将这些排行数据放到model中去,因此对于后端来说这也是一个重复性的工作。那么有没有一种方式可以让后端也脱离这种重复工作呢?答案是肯定的,这也是写这篇博客的目的。

在一个偶然的机会发现jeecms项目中用到了这种方式,于是借鉴了一番。

FreeMarker不仅可以在前端的模板页中定义宏,还可以通过扩展其接口在后端实现宏,这有什么好处呢?这种方式就好比让你的模板页具备了从前端再次回到后端的能力。这样我们就能很好的解决【1】处的假设,我们无需在各个controller的各个接口中去重复的向model中添加所需的排行数据,而是当FreeMarker渲染模板页时遇到相应的宏它可以回到后端去调用相应的方法取到所需的数据。例子如下:

  1. import freemarker.core.Environment;
  2. import freemarker.template.ObjectWrapper;
  3. import freemarker.template.TemplateDirectiveModel;
  4. /**
  5. * FreeMarker自定义宏
  6. * 获取App下载排行列表
  7. * 参数包括 length(列表长度) mtypeCode(主类型代码) typeCode(小类型代码) rankMode(排行模式1、2、3)
  8. * @author shannon
  9. *
  10. */
  11. public class FMAppRankDirective implements TemplateDirectiveModel {
  12. @Resource(name = "appRankService")
  13. private AppRankService appRankService;
  14. @SuppressWarnings("unchecked")
  15. @Override
  16. public void execute(Environment env, Map params, TemplateModel[] loopVars,
  17. TemplateDirectiveBody body) throws TemplateException, IOException {
  18. //DirectiveUtils是借用jeecms项目中的工具类,主要是因为它集成了一些异常处理功能,
  19. //其实完全可以不用它,params是个Map,自己通过key取值就可以了,做一下空值判断
  20. Integer length = DirectiveUtils.getInt("length", params);
  21. Integer mtypeCode = DirectiveUtils.getInt("mtypeCode", params);
  22. Integer typeCode = DirectiveUtils.getInt("typeCode", params);
  23. Integer rankMode = DirectiveUtils.getInt("rankMode", params);
  24. ArrayList<App> rankList = appRankService.getRankList(length, mtypeCode, typeCode, rankMode);
  25. env.setVariable("appRankList", ObjectWrapper.DEFAULT_WRAPPER.wrap(rankList));
  26. if (body != null) {
  27. body.render(env.getOut());
  28. }
  29. }
  30. }

通过实现FreeMarker的TemplateDirectiveModel就在后端实现了一个自定义的宏,这个宏的功能很简单,只是根据给定的参数将排行数据“appRankList”放到model中去,然后模板页中就可以使用这个变量了。

FreeMarker的配置参数中需要将这个宏加入进去。

  1. <bean id="appRankDirective" class="com.shannon.example.rank.util.FMAppRankDirective" />
  2. <bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  3. ……其他配置略……
  4. <property name="freemarkerVariables">
  5. <map>
  6. ……其他配置略……
  7. <entry key="appRankDirective" value-ref="appRankDirective"/>
  8. </map>
  9. </property>
  10. </bean>

在模板页中使用:

  1. <#-- 应用下载排行框,title为该框的标题,length为排行列表长度,mtypeCode为主类型代码,typeCode为小类型代码,rankMode为排行方式
  2. 1为总下载量,2为月下载量,3为昨日增长下载量
  3. -->
  4. <#macro appRankBox title="" length=10 mtypeCode=1 typeCode=-1 rankMode=1>
  5. <@appRankDirective length=length mtypeCode=mtypeCode typeCode=typeCode rankMode=rankMode />
  6. <h3 class="box-title">${title}</h3>
  7. <div class="box">
  8. <ul class="row-list">
  9. <#list appRankList as item>
  10. ……详细输出内容略……
  11. </#list>
  12. </ul>
  13. </div>
  14. </#macro>

这里我在模板页中又定义了一个宏,负责内容及样式的输出,因为模板页中的宏比较直观,让后端的宏只负责拿数据。其他页面直接使用“appRankBox”就可以了,然后由它来调用后端的“appRankDirective”宏来拿数据。

这样,controller就从重复工作中脱身了。

FreeMarker自定义TemplateDirectiveModel的更多相关文章

  1. 关于FreeMarker自定义TemplateDirectiveModel

    [转载来源:http://zwllxs.iteye.com/blog/2036826] java代码如下: import freemarker.core.Environment; import fre ...

  2. FreeMarker 自定义 TemplateDirectiveModel(二)

    FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不 ...

  3. FreeMarker 自定义 TemplateDirectiveModel(一)

    FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP.它不 ...

  4. 基于SSM3框架FreeMarker自定义指令(标签)实现

    通过之前的Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解系列文章,我们已经成功的整合到了一起,这次大象将在此基础上对框架中的FreeMarker模板 ...

  5. freemarker自定义标签(与java合用)

    自定义类继承FreemarkerManager类,重写protected Configuration createConfiguration(ServletContext servletContext ...

  6. OneBlog开源博客-详细介绍如何实现freemarker自定义标签

    前言 OneBlog中使用到了springboot + freemarker的技术,同时项目里多个controller中都需要查询一个公有的数据集合,一般做法是直接在每个controller的方法中通 ...

  7. freemarker 自定义标签

    1.编写标签类 package com.pccw.business.fnd.common.filegen; import java.io.IOException; import java.io.Wri ...

  8. freemarker自定义标签报错(六)

    freemarker自定义标签 1.错误描述 freemarker.core.ParseException: Encountered "\"\u4f60\u597d\uff01\& ...

  9. freemarker自定义标签报错(五)

    freemarker自定义标签 1.错误描述 六月 05, 2014 11:40:49 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严 ...

随机推荐

  1. sql server 跨数据库调用存储过程

    A库存储过程: create PROCEDURE [dbo].[spAAAForTest] ( ) =null , ) =null ) AS BEGIN select N'A' AS a , N'B' ...

  2. 读书笔记: Microsot .NET企业级应用架构设计

    Microsot .NET企业级应用架构设计 Dino Esposito   Andrea Saltarello 编    陈黎夫 译   人民邮电出版社 第一部分 设计原则 第1章 当代架构师和架构 ...

  3. NoSQL&&Redis介绍

    再说Redis之前,想先说一下NoSQL.在最早的单机时代,随着数据的增加一台机器可能放不下了.同时索引占用的内存空间也会越来越大.对请求的读写操作影响很大.于是就在数据库之前增加了一层保护层 — 缓 ...

  4. sql数据类型转换函数

    1.CAST()CAST (<expression> AS <data_ type>[ length ]) 2.CONVERT()CONVERT (<data_ type ...

  5. java socket 判断Socket连接失效

    要判断socket连接链路是否可用时,不能通过socket.isClosed() 和 socket.isConnected() 方法判断,要通过心跳包 socket.sendUrgentData(0x ...

  6. 2-5-NFS服务器配置和autofs自动挂载-配置Samba服务器配置现实文件共享

    大纲: NFS服务器运行原理 实战配置NFS服务器 配置Samba服务器配置现实文件共享 ----------------------------------------------- 问题: # 怎 ...

  7. SSH集成log4j日志环境

    第一步:在web.xml初始化log4j <context-param> <param-name>contextConfigLocation</param-name> ...

  8. OC与JS的交互详解

    事情的起因还是因为项目需求驱动.折腾了两天,由于之前没有UIWebView与JS交互的经历,并且觉得这次在功能上有一定的创造性,特此留下一点文字,方便日后回顾. 我要实现这样一个需求:按照本地的CSS ...

  9. 【hive】lateral view的使用

    当使用UDTF函数的时候,hive只允许对拆分字段进行访问的 例如: select id,explode(arry1) from table; —错误 会报错FAILED: SemanticExcep ...

  10. jq中的$.post中方法

    jQuery.post( url, [data], [callback], [type] ) : 使用POST方式来进行异步请求 参数: url (String) : 发送请求的URL地址. data ...