freemarker的宏功能非常强大,但是也有局限性,比如不能像jsp tag一样,访问父tag的参数,不利于复杂macro的封装,闭门研究freemarker代码三天,基本实现了宏的嵌套调用问题,特分享之
比如下面这个tag嵌套,是一个对ext grid的封装:
<g:list id="gridobj" width="100%" checkbox="true"
keyField="NEW_ID" splitInfo="splitParam"
rowdbclick="rowdbclick" contentHeightOffset="-100">
<g:query>
<g:queryItem label="名称" name="NEW_TITLE" />
<g:queryItem label="时间(起)" itemType="datefield" name="NEW_DATE1" />
<g:queryItem label="时间(止)" itemType="datefield" name="NEW_DATE2" />
</g:query>
<g:field fieldname="NEW_ID" header="编号" width="80" hidden="true" />
<g:field fieldname="STATUS" header="图片" width="35" renderer="statusHandler"/>
<g:field fieldname="NEW_TITLE" header="项目名称" width="230" />
<g:field fieldname="NEW_SUMMARY" header="新闻摘要" width="300" renderer="summaryHandler"/>
<g:field fieldname="NEW_DATE" header="时间" width="85" renderer="dateformat" />
<g:field fieldname="IMAGE_URL" header="新闻路径" width="100" hidden="true"/>
</g:list>
但是freemarker macro没有这个能力,在宏的嵌套body中,只能在宏中通过<#nested>来访问标签之间的文本,或者直接用参数传过去,而不能在tag之间设置tag的参数,宏的局部变量对宏tag之间的body也是隐藏的
为此我开发了两个directive
ExposeDirective
ParamDirective
ExposeDirective实现了把当前宏的macroContext导出到全局变量,同是如果发现自己被宏调用嵌套,则创建一个变量保存父宏的macroContext,达到访问父宏上下文的目的
Macro.Context mc = env.getCurrentMacroContext();
if (mc == null) {
throw new TemplateException("macro context not found,this directive must be call in macro", env);
}
List stack = DirectiveHelper.getElementStack(env);
Object macroCall = null, parentMacroCall = null;
for (int i = stack.size() - 1; i > -1; i--) { //遍历当前运行时堆栈,找到当前宏的UnifiedCall
if (stack.get(i) instanceof Macro) {
Object call = stack.get(i - 1);
if (macroCall == null) {
macroCall = call;
} else {
parentMacroCall = call;
break;
}
}
}
DirectiveHelper.exposeMacroContext(env, macroCall, mc);//暴露当前宏local变量上下文到全局上下文
if (parentMacroCall == null)
return;
Macro.Context parentMc = (Macro.Context) DirectiveHelper.getMacroContext(env, parentMacroCall);//获取父宏上下文
if (parentMc != null)
mc.setLocalVar(DirectiveHelper.getParam(params, "parent", "parent"), parentMc.getLocals());//在当前宏上下文中保存一个叫parent的变量,值为父宏的local变量
ParamDirective则根据当前的调用堆栈找到macroContext,从而可以访问到宏的局部变量,实现了宏的嵌套使用,并且支持复杂的参数设置
请看例子:
设置变量
<#macro outer name="ozn" age="27" sex="boy">
<@expose/>
<#nested>
</#macro>
<#macro inner parent={}>
<@expose/>
<@param name="parent.name" value="cici"/>
${parent.name}
</#macro>
<@outer><@inner/></@>
使用body来设置变量值
<@param name="addr.area">${addr.country}</@>
删除变量
<#macro outer name="ozn" age="27" sex="boy">
<@expose/>
<#nested>
</#macro>
<#macro inner parent={}>
<@expose/>
<@param name="parent.name" action="remove"/>
${parent?keys?size}
</#macro>
<@outer><@inner/></@>
添加变量
<#macro hello name=["ozn","cici"]>
<@expose/>
<#nested>
${name?size}
</#macro>
<@hello><@param name="name" value="me" action="add"/></@>
更多例子请看代码里面的testCase
另附上覆盖率测试图
有任何问题,请不吝赐教
代码托管于:
http://code.google.com/p/freemarker-sweet/
分享到:
相关推荐
camel-freemarker-1.6.4.jar, camel-freemarker-2.8.1.jar, com.springsource.freemarker-2.3.15.jar, com.springsource.freemarker-sources-2.3.15.jar, freemarker-1.4.1.jar, freemarker-2-3-18.jar, freemarker-...
赠送jar包:freemarker-2.3.30.jar; 赠送原API文档:freemarker-2.3.30-javadoc.jar; 赠送源代码:freemarker-2.3.30-sources.jar; 赠送Maven依赖信息文件:freemarker-2.3.30.pom; 包含翻译后的API文档:...
其中可能涉及一些链家网、H-ui等相关的信息,在这里说明,本项目仅供交流学习,不得用于商业传播)基于springboot+MyBatis+FreeMarker+redis+nginx等技术的JavaWeb项目------恋家房产平台先简单放几张项目的图吧,...
6. **指令(Directive)**:用于控制模板的逻辑,如#if、#foreach等,它们可以嵌套使用,实现复杂的条件判断和循环。 7. **控制结构(Control Structures)**:类似于编程语言中的流程控制语句,如条件语句和循环...
JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-2.3.8JavaEE源代码 freemarker-...
在使用Freemarker时,首先需要配置和初始化`freemarker.template.Configuration`对象,设置模板目录和输出字符集等参数。然后,创建一个`Template`对象,加载模板文件。接着,准备一个数据模型,通常是Java对象或Map...
赠送jar包:freemarker-2.3.30.jar; 赠送原API文档:freemarker-2.3.30-javadoc.jar; 赠送源代码:freemarker-2.3.30-sources.jar; 赠送Maven依赖信息文件:freemarker-2.3.30.pom; 包含翻译后的API文档:...
赠送jar包:freemarker-2.3.31.jar; 赠送原API文档:freemarker-2.3.31-javadoc.jar; 赠送源代码:freemarker-2.3.31-sources.jar; 赠送Maven依赖信息文件:freemarker-2.3.31.pom; 包含翻译后的API文档:...
`freemarker.jar`是Freemarker库的二进制文件,它是实际运行时需要导入到Java项目的类路径中的,以便使用Freemarker的功能,如创建模板、解析数据模型并生成最终输出。 `source`目录可能包含了Freemarker 2.3.22的...
### jsp、freemarker、velocity简介和对比 在Java Web开发领域,模板引擎是连接后端业务逻辑与前端展示层的重要桥梁。本文将重点介绍三种常用的Java Web模板引擎:JSP(Java Server Pages)、Freemarker以及...
经测试这样方式生成的word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。 word的几个主要xml标志 w:body 正文内容 w:p 一个段落 w:tbl 表格数据 w...
spring-boot-starter-freemarker-1.5.4.RELEASE.jar
Freemarker是一个强大的模板引擎,常用于Web应用中动态生成HTML或其他类型的静态页面。它采用声明式编程方式,...在实际开发中,结合具体的项目需求,可以进一步探索和优化Freemarker的使用方式,实现更复杂的功能。
这个"freemarker-2.3.28.jar"文件可能是Eclipse插件的一部分,意味着它可以方便地在Eclipse环境中配置和使用Freemarker,提供代码提示、自动完成、错误检查等功能,从而提高开发效率。 在实际应用中,开发者通常会...
- 这个版本可能包含了一些基本的功能,如模板语言的语法,变量、表达式和控制结构。 - 它可能已经支持了数据模型绑定,允许开发者将Java对象的数据传递给模板进行渲染。 - 可能包括了基本的错误处理机制和调试...
标题 "原创 用FreeMarker宏 和 Jquery 做树(Hbiernate和JDBC版)" 描述了如何使用FreeMarker模板引擎的宏功能,结合jQuery库,创建一个可展示层次结构数据的树形视图。在这个过程中,可能涉及了两个主要的技术:...
freemarker-2.3.22.jar用于生成word模板核心工具包,非常好用!详细操作使用,请参考我的文章链接:https://blog.csdn.net/qq_45978154/article/details/125065400?spm=1001.2014.3001.5502
FreeMarker 是一个强大的模板引擎,常用于Java Web开发...记住,学习和理解FreeMarker的宏机制是关键,这有助于你在实际项目中灵活应用和扩展分页功能。通过这种方式,你可以创建一个既高效又易于维护的分页解决方案。
5. **自定义指令**:可以扩展FreeMarker,实现自定义的模板指令和函数。 ### 学习资源 这份2015年10月7日的FreeMarker中文手册是学习和解决问题的重要参考,其中详细介绍了FreeMarker的语法、配置、最佳实践等内容...
在项目中难免和各种数据报表打交道,如导出XX申请表,登记表,推荐表之类。就可以通过现有信息导出Word文档。基于Java语言来导出Word文档的方式也有很多种,如Jacob,Apache POI,Freemarker,PageOffice,java2word...