我最近发现了jsp标签并使用它们来避免重复我视图的常见部分。
所以在我的JSP视图中我有
<web-component:mytag>
<!-- HTML specific to that page -->
</web-component:mytag>
在我的代码文件中,我获得了带有<jsp:doBody/>
的HTML。
我的问题是,如何测试<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>
所以我正在寻找doBody.empty
提前致谢。
答案 0 :(得分:8)
您有三种选择,每种选择都有其优缺点。
<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>
为什么使用
${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>
并且页面定义了trimDirectiveWhitespaces="true"
,您的标记文件将检测到没有正文。如果trimDirectiveWhitespaces="false"
,您的代码文件将检测到有正文。
请注意,这仅适用于标记文件,而不适用于简单/经典标记处理程序。在上面的示例中,如果在标记处理程序中定义了<my:tag>
,则无论空白设置如何,处理程序的行为都会像主体一样:
getJspBody()
将为非null。doAfterBody()
。您可以通过使用Java代码测试null body来消除第一个解决方案的缺点。这个解决方案和下一个解决方案就是这样做的,除了这个解决方案更简单并且使用了一个小脚本。
<c:choose>
<c:when test="<%= super.getJspBody() != null %>">
<jsp:doBody />
</c:when>
<c:otherwise>
<!-- My default HTML content here -->
</c:otherwise>
</c:choose>
这样做的原因是标记文件被转换为扩展SimpleTagSupport
的处理程序(请参阅javax.servlet.jsp.tagext),并且在处理程序的doTag()
方法中执行scriptlet。因此,super.getJspBody() == null
的工作方式与您在任何简单标记处理程序中的预期相同。
在不执行正文的情况下完成对空体的测试。
正文未存储在变量中。
scripting-invalid
配置如何,都允许标记文件使用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);
}
}
现在你的标签文件看起来像这样:
<my:hasBody />
<c:choose>
<c:when test="${hasBody}">
<jsp:doBody />
</c:when>
<c:otherwise>
<!-- Default content here -->
</c:otherwise>
</c:choose>
@Ryan想知道如何将此方法应用于一般JSPFragment
属性。幸运的是,因为所有属性都可以作为EL中的变量直接访问(而实体不是),测试空片段属性是微不足道的:
<%@ attribute name="frag" fragment="true" %>
<c:choose>
<c:when test="${frag != null}">
<jsp:invoke fragment="frag" />
</c:when>
<c:otherwise>
<!-- Default content here -->
</c:otherwise>
</c:choose>
答案 1 :(得分:0)
你可以这样做。
<jsp:doBody var="bodyText"/>
<c:if test="${not empty bodyText}">
//will shown if its not empty
</c:if>