【发布时间】:2014-01-16 00:31:21
【问题描述】:
有什么方法可以在一个 JSP 页面上制作某种参数化宏,并在同一页面上重复使用几次。可以使用 JSP 标记,但我必须为每个标记创建一个文件。
【问题讨论】:
标签: jsp macros tags parameter-passing code-reuse
有什么方法可以在一个 JSP 页面上制作某种参数化宏,并在同一页面上重复使用几次。可以使用 JSP 标记,但我必须为每个标记创建一个文件。
【问题讨论】:
标签: jsp macros tags parameter-passing code-reuse
多年来我一直想要这个功能,在再次谷歌搜索之后,我编写了自己的功能。我认为标签 / 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" >↑</span>
<span class="desc">↓</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 内置的。
【讨论】:
我尝试了 Johnny 的解决方案,发现如果多次使用宏,就会出现错误。
您必须在重新处理后从页面上下文中删除属性
jspFragment.invoke(getJspContext().getOut());
for (String key : attributes.keySet()) {
ctx.removeAttribute(key);
}
【讨论】: