我最近发现了jsp标签并使用它们来避免重复我的视图的常见部分.
所以在我的JSP视图中我有
<web-component:mytag>
<!-- HTML specific to that page -->
</web-component:mytag>
Run Code Online (Sandbox Code Playgroud)
在我的标签文件中,我得到了HTML <jsp:doBody/>.
我的问题是,如何测试是否<jsp:doBody/>为空,以便我可以放置默认的HTML内容?
就像是
<c:choose>
<c:when test="${!doBody.empty}">
<jsp:doBody/>
</c:when>
<c:otherwise>
<!-- My default HTML content here -->
</c:otherwise>
</c:choose>
Run Code Online (Sandbox Code Playgroud)
所以我正在寻找正确的表达方式 doBody.empty
提前致谢.
您有三种选择,每种选择都有其优缺点.
<jsp:doBody var="bodyText" />这可能是最常见和最明显的解决方案.
执行一次主体,将其输出存储在变量中,并检查该变量是否为空.
<jsp:doBody var="bodyText"/>
<c:choose>
<c:when test="${not empty fn:trim(bodyText)}">
${bodyText}
</c:when>
<c:otherwise>
<!-- Default content here -->
</c:otherwise>
</c:choose>
Run Code Online (Sandbox Code Playgroud)
为什么要使用
${not empty fn:trim(bodyText)}而不是更简单的条件${empty bodyText}?感谢@ach,他指出了这一点,后者修剪了空白,因此无论trimDirectiveWhitespaces设置如何都表现一致.
身体总是被执行.您可能不想执行标记体(以及任何副作用)只是为了测试它的存在.
标签主体的全部内容都存储在内存中.对于较长的标签主体,这可能是一个问题.
(使用时请忽略这一点${not empty fn:trim(bodyText)}.仅适用于${empty bodyText}.)
条件是否${empty bodyText}为真取决于调用JSP是否启用trimDirectiveWhitespaces.
当标签的主体只包含空格时
<%@ page trimDirectiveWhitespaces="true" %>
<my:tag value="a">
</my:tag>
Run Code Online (Sandbox Code Playgroud)
并且页面定义了trimDirectiveWhitespaces="true",您的标记文件将检测到没有正文.如果trimDirectiveWhitespaces="false",您的标记文件将检测到有正文.
请注意,这仅适用于标记文件,而不适用于简单/经典标记处理程序.在上面的示例中,如果<my:tag>在标记处理程序中定义,则无论空白设置如何,处理程序的行为都会像正文一样存在:
getJspBody()将为非null.doAfterBody()将被调用.您可以通过使用Java代码测试null body来消除第一个解决方案的缺点.这个解决方案和下一个解决方案完全相同,除了这个更简单并使用scriptlet.
<c:choose>
<c:when test="<%= super.getJspBody() != null %>">
<jsp:doBody />
</c:when>
<c:otherwise>
<!-- My default HTML content here -->
</c:otherwise>
</c:choose>
Run Code Online (Sandbox Code Playgroud)
这样做的原因是标记文件被转换为扩展的处理程序SimpleTagSupport(请参阅javax.servlet.jsp.tagext),并且scriptlet在处理程序的doTag()方法中执行.因此super.getJspBody() == null在任何简单的标记处理程序中的工作方式与您期望的相同.
无需执行主体即可完成对空体的测试.
正文不存储在变量中.
scripting-invalidJSP文件的配置如何,都允许标记文件使用scriptlet .)如果您需要scriptlet解决方案的功能而不实际使用scriptlet,请继续阅读.
这里的想法是将body null测试封装在从标记文件调用的标记处理程序中.标签处理程序可以通过getParent()和访问标记文件,并将布尔测试结果导出为变量:
class HasBody extends SimpleTag {
@Override
public void doTag() throws JspException {
TagAdapter adapter = (TagAdapter)this.getParent();
SimpleTagSupport parent = (SimpleTagSupport)adapter.getAdaptee();
// `getJspBody()` is a protected method, so actually you must use reflection.
JspFragment body = parent.getJspBody();
this.getJspContext().setAttribute("hasBody", body == null);
}
}
Run Code Online (Sandbox Code Playgroud)
现在你的标签文件看起来像这样:
<my:hasBody />
<c:choose>
<c:when test="${hasBody}">
<jsp:doBody />
</c:when>
<c:otherwise>
<!-- Default content here -->
</c:otherwise>
</c:choose>
Run Code Online (Sandbox Code Playgroud)