有没有办法在一个JSP页面上制作某种参数化宏,并在同一页面上重复使用几次。可以使用JSP标记,但我必须为每个标记创建一个文件。
我多年来一直想要这个功能,再次谷歌搜索后,我写了自己的功能。我认为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" >↑</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的解决方案,发现如果你多次使用宏,那就有一个bug。
您必须在渲染后从页面内容中删除属性
jspFragment.invoke(getJspContext().getOut());
for (String key : attributes.keySet()) {
ctx.removeAttribute(key);
}