FreeMarker 自定义 TemplateDirectiveModel(二)
FreeMarker 是一个用 Java 语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker 与 Web 容器无关,即在 Web 运行时,它并不知道 Servlet 或 HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成 XML,JSP 或 Java 等。 摘要: 采用的是 freemarker 版本 2.3.21 采用 BeansWrapperBuilder 替代 DEFAULT_WRAPPER 的方式。 自定义标签需要实现 TemplateDirectiveModel 这个接口中的 execute 方法 实例代码如下
public class UserListDirective implements TemplateDirectiveModel{ @Autowired
private UserDAO userDao;
@Override
public void execute(Environment env, Map params, TemplateModel[] loopVars,
TemplateDirectiveBody body)
throws TemplateException, IOException {
String name = params.get("name").toString();
List<User> userlist = userDao.findByProperty("name", name); env.setVariable("userList", getBeansWrapper().wrap(userlist));
body.render(env.getOut());
} public static BeansWrapper getBeansWrapper(){
BeansWrapper beansWrapper =
new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
return beansWrapper;
}
}
配置 UserListDirective 到 spring bean xml 中
<bean id="userListDirective" class="com.action.directive.UserListDirective"></bean>
将 spring bean 设置到 freemarkerConfig 全局变量中去。
<bean id="freemarkerConfig2"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/" />
<property name="freemarkerVariables">
<map >
<entry key="userListDirective" value="userListTag" />
</map>
</property>
<property name="freemarkerSettings">
<props>
<prop key="template_update_delay">0</prop>
<prop key="defaultEncoding">UTF-8</prop>
<prop key="url_escaping_charset">UTF-8</prop>
<prop key="locale">zh_CN</prop>
<prop key="boolean_format">true,false</prop>
<prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>
<prop key="date_format">yyyy-MM-dd</prop>
<prop key="time_format">HH:mm:ss</prop>
<prop key="number_format">0.######</prop>
<prop key="whitespace_stripping">true</prop>
</props>
</property>
</bean>
ftl 文件中的访问方式
<@userListTag name="zhangsan">
<#if userList?? && userList?size gt 0>
<#list userList as user>
<a href="">${user.name}</a>
</#list>
</#if>
</@userListTag>
freemarker 遍历 map
第一种方式(2.3.21 版本之前好像可以用) <#list testMap?keys as testKey>
< option value="${testKey}" >
${testMap.get(testKey)}
</option>
</#list>
<#list testMap.keySet() as testKey>
< option value="${testKey}" >
${testMap.get(testKey)}
</option>
</#list>
附摘:
在采用 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
[参考:http://blog.csdn.net/fangzhangsc2006/article/details/8687371] 在采用FreeMarker做前台视图模板的情况下,我们可以通过< ...
- freemarker自定义标签(二十一)
一,讲解一 1.自定义标签说明 宏变量存储模板片段可以被用作自定义指令macro 2.示例说明 <html> <head> <meta http-equiv=" ...
- freemarker自定义标签报错(二)
freemarker自定义标签 1.错误描述 freemarker.core.ParseException: Unexpected end of file reached. at freemarker ...
- freemarker自定义标签(二)
freemarker自定义标签 1.自定义标签 通过自定义标签,写一个重复指定字符串 2.实现源码 <html> <head> <meta http-equiv=&quo ...
- OneBlog开源博客-详细介绍如何实现freemarker自定义标签
前言 OneBlog中使用到了springboot + freemarker的技术,同时项目里多个controller中都需要查询一个公有的数据集合,一般做法是直接在每个controller的方法中通 ...
- 基于SSM3框架FreeMarker自定义指令(标签)实现
通过之前的Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解系列文章,我们已经成功的整合到了一起,这次大象将在此基础上对框架中的FreeMarker模板 ...
- freemarker自定义标签(与java合用)
自定义类继承FreemarkerManager类,重写protected Configuration createConfiguration(ServletContext servletContext ...
随机推荐
- scrapy的使用--Rcrapy-Redis
Scrapy-Redis分布式爬虫组件 Scrapy是一个框架,他本身是不支持分布式的.如果我们想要做分布式的爬虫.就需要借助一个组件叫做Scrapy-Redis.这个组件正式利用了Redis可以分布 ...
- uoj118 【UR #8】赴京赶考
题目 不难发现我们直接走过去就行了 考虑到第\(i\)行的构造方法就是把\(b\)数组作为模板,每个数和\(a_i\)异或一下就可以了 于是不难发现对于一段连续相等的\(a\),它们在矩阵上就形成了完 ...
- ubuntu安装更新命令
ubuntu16.04LTS 进入ubuntu系统后,打开一个终端,如图所示.此时以普通用户身份登录. 由于更新系统需要用到管理员权限,因此要么使用"su -"直接切换到roo ...
- 2019 Multi-University Training Contest 7 Kejin Player 期望dp
题目传送门 题意:有n个等级,在每个等级花费$ai$的代价有$pi$的几率升到$i+1$级,$1-pi$的概率降级降到$xi$(xi<=i),给出q次询问,每次询问从$l$级到$r$级的代价的期 ...
- Python学习笔记(四)——文件永久存储
文件的永久存储 pickle模块的使用 pickle的实质就是将数据对象以二进制的形式存储 存储数据 pickle.dump(data,file) data表示想要存储的数据元素,file表示要将数据 ...
- A decorative fence
A decorative fence 在\(1\sim n\)的全排列\(\{a_i\}\)中,只有大小交错的(即任意一个位置i满足\(a_{i-1}<a_i>a_{i+1}ora_{i- ...
- 0914CSP-S模拟测试赛后总结
9-16 16:03-upd:T3数据出锅,老师重测了,于是更了榜单. 名次并没有变化,但是和大佬们的差距变大了. 还是自己实力不行啊.最起码T3不是特别难想吧. 继续努力吧. 粘个榜:%%%二营长. ...
- 7_3.springboot2.x启动配置原理_3.事件监听机制
事件监听机制配置在META-INF/spring.factories ApplicationContextInitializer SpringApplicationRunListenerioc容器中的 ...
- Query Rewrite Plugins
[root@ZST1 ~] mysql -- </usr/local/mysql/share/install_rewriter.sql mydba@ [(none)]> create da ...
- Censored! POJ - 1625 AC自动机+大数DP
题意: 给出一n种字符的字典,有p个禁用的单词, 问能组成多少个不同的长度为m的合法字符串.(m<=50) 题解: 是不是个我们之前做的题目非常非常像,题意都一样. 直接将上次写的AC自动机+矩 ...