简单扩展让beetl HTML标签支持父子嵌套

默认情况下,Beetl的html标签并不支持父子嵌套,就像类似jsp标签那样,父标签需要知道子标签的信息,子标签也需要知道父标签信息。但是beetl只需要简单扩展,就能完成嵌套标签支持。

首先看一个最终的使用效果,实现俩个html标签table.tag,tr.tag.可以在页面上这么用:

<#table data ="${userList}">
<#tr class="3c" name="name"> 名称 </#tr>
</#table>



在阅读table.tag,tr.tag之前,先看看如何扩展html标签
首先,需要扩展 HTMLTagSupportWrapper,这个类是html标签实现类,我们可以扩展此类来定制化需求,然后重新注册覆盖。因此实现类

public class HTMLNestTagSupportWrapper extends HTMLTagSupportWrapper{
public void render(){....}
}



然后在配置文件配置TAG.htmltag= bingo.util.HTMLNestTagSupportWrapper 就可以生效。

HTMLNestTagSupportWrapper用到了TagNestContext类,这个类其实就是一个树形结构,记录了parent的Context,记录了当前tag信息,以及记录了子tag的Context,这样,每个tag都可以访问父tag或者子tag:代码如下

public class TagNestContext {
private  Tag tag = null;
private TagNestContext parent = null;
private List<TagNestContext> children = null;
public  Tag getTag() {
    return tag;
}
public void setTag(Tag para) {
    this.tag = para;
}
public TagNestContext getParent() {
    return parent;
}
public void setParent(TagNestContext parent) {
    this.parent = parent;
}
public List<TagNestContext> getChildren() {
    if(children==null) children = new ArrayList<TagNestContext>();
    return children;
}
public void setChildren(List<TagNestContext> children) {
    this.children = children;
}

}



回头在看看 HTMLNestTagSupportWrapper实现

public void render()
{
    HttpServletRequest request = (HttpServletRequest)this.ctx.getGlobal("request");
    TagNestContext tnc = (TagNestContext)request.getAttribute("tagContext");
    if(tnc==null){
        tnc = new TagNestContext();
        tnc.setTag(this);
        request.setAttribute("tagContext", tnc);
        super.render();
        request.removeAttribute("tagContext");


    }else{
        TagNestContext child = new TagNestContext();
        child.setParent(tnc);
        child.setTag(this);
        tnc.getChildren().add(child);
        request.setAttribute("tagContext", child);
        super.render();
        //重新设置
        request.setAttribute("tagContext", child.getParent());

    }




}

public String getTagName(){
    return (String)this.args[0];
}

public Object get(String attr){
    Map map =  (Map)this.args[1];
    return map.get(attr);
}



如上代码所示,但渲染某个htmltag前(调用super.render()前),可以从request里获取NestContext,如果没有,生成一个新的NestContext。如果已经存在。则将当前NestContext加入到父NestContext。渲染完毕后,需要重置NestContext。

最后看一下tr.tag如何实现,tr仅仅实现了生成表头

<tr class="${class}">${tagBody}</tr>



table.tag 则要麻烦点,需要知道有多少个tr,然后输出数据,内容如下:

<table>
${tagBody}
<% for(var item in data){%>
<tr>
<%

var tag = getTagContext();
var children = tag.children;
for(var tdTagCtx in children){
    print("<td>");
    var tdTag = tdTagCtx.tag;
    var name = tdTag.tagName;
    var value = item[name];
    print(value);
    println("</td>");
}


%>
</tr>
<%} %>
</table>



etTagContext 是一个注册方法,获取当前context.可以自行开发一个

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。