原创freemarker功能增强小项目freemarker-sweet,实现了类似jsp tag的宏的嵌套调用和复杂参数设置...

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

另附上覆盖率测试图
[img]http://freemarker-sweet.googlecode.com/svn/wiki/freemarker.jpg[/img]
有任何问题,请不吝赐教

代码托管于:
[url]http://code.google.com/p/freemarker-sweet/[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值