JSP:创建可重用的代码(标记,宏)并在同一页面上使用它

问题描述 投票:2回答:2

有没有办法在一个JSP页面上制作某种参数化宏,并在同一页面上重复使用几次。可以使用JSP标记,但我必须为每个标记创建一个文件。

jsp macros tags parameter-passing code-reuse
2个回答
3
投票

我多年来一直想要这个功能,再次谷歌搜索后,我写了自己的功能。我认为tag / jsp文件和自定义标记类很棒,但对于像你描述的简单的一次性文章来说往往有点过分。

这就是我的新“宏”标签现在的工作原理(这里用于可排序表头的简单html呈现):

<%@ taglib prefix="tt" uri="/WEB-INF/tld/tags.tld" %>

<!-- define a macro to render a sortable header -->
<tt:macro id="sortable">
    <th class="sortable">${headerName}
        <span class="asc" >&uarr;</span>
        <span class="desc">&darr;</span>
    </th>
</tt:macro>

<table><thead><tr>
    <!-- use the macro for named headers -->
    <tt:macro id="sortable" headerName="Name (this is sortable)" />
    <tt:macro id="sortable" headerName="Age (this is sortable)" />
    <th>Sex (not sortable)</th>
    <!-- etc, etc -->

在/WEB-INF/tld/tags.tld中,我补充说:

<tag>
    <name>macro</name>
    <tag-class>com.acme.web.taglib.MacroTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
        <description>ID of macro to call or define</description>
        <name>id</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <dynamic-attributes>true</dynamic-attributes>
</tag>

最后,Java标记类:

public class MacroTag
    extends SimpleTagSupport implements DynamicAttributes
{
    public static final String PREFIX = "MacroTag_";
    private boolean bodyless = true;
    private String id;
    private Map<String, Object> attributes = new HashMap<String, Object>();

    @Override public void setJspBody(JspFragment jspFragment) {
        super.setJspBody(jspFragment);
        getJspContext().setAttribute(PREFIX + id, jspFragment, PageContext.REQUEST_SCOPE);
        bodyless = false;
    }

    @Override public void doTag() throws JspException, IOException {
        if (bodyless) {
            JspFragment jspFragment = (JspFragment) getJspContext().getAttribute(PREFIX + id, PageContext.REQUEST_SCOPE);
            JspContext ctx = jspFragment.getJspContext();
            for (String key : attributes.keySet())
                ctx.setAttribute(key, attributes.get(key));
            jspFragment.invoke(getJspContext().getOut());
            for (String key : attributes.keySet()) {
                ctx.removeAttribute(key);
            }
        }
    }

    public void setId(String id) {
        this.id = id;
    }
    @Override public void setDynamicAttribute(String uri, String key, Object val) throws JspException {
        attributes.put(key, val);
    }
}

实施非常基础。如果标签有一个主体,我们假设我们正在定义一个宏,并且我们存储了JspFragment。否则,我们假设我们正在调用一个宏,所以我们查找它,并将任何动态属性复制到其上下文中,以便正确参数化,并将其呈现到调用输出流中。

疯狂这不是内置于JSP中的。


1
投票

我尝试了Johnny的解决方案,发现如果你多次使用宏,那就有一个bug。

您必须在渲染后从页面内容中删除属性

jspFragment.invoke(getJspContext().getOut());

for (String key : attributes.keySet()) {
    ctx.removeAttribute(key);
}
© www.soinside.com 2019 - 2024. All rights reserved.