java JSF 渲染:EL 语句的条件不正确

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12323058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 08:26:18  来源:igfitidea点击:

JSF rendering: condition of EL statement incorrect

javajsfrenderingelconditional-statements

提问by Menno

I have got a problem with my JSF-rendering. A given condition in Expression Language will not be executed in the right way. E.g:

我的 JSF 渲染有问题。表达式语言中的给定条件不会以正确的方式执行。例如:

Example 1

示例 1

<f:param name="cat" value="#{product.category.uri}" rendered="#{product.category.parent.uri == null}" />
<f:param name="cat" value="#{product.category.parent.uri}" rendered="#{product.category.parent.uri != null}" />

Example 2

示例 2

<c:if test="#{product.category.parent.uri == null}">
    <f:param name="cat" value="#{product.category.uri}" />
</c:if>

<c:if test="#{product.category.parent.uri != null}">
    <f:param name="cat" value="#{product.category.parent.uri}" />
</c:if>

Problem

问题

In both examples, both my parameters will be added to my surrounding h:outputLink. I am not sure what other code to add, so if you guys need anything else in order to help me, I'll be happy to provide it.

在这两个示例中,我的两个参数都将添加到我周围的 h:outputLink 中。我不确定要添加什么其他代码,所以如果你们需要其他任何东西来帮助我,我很乐意提供。

Thanks in advance.

提前致谢。

Example 3 (on request)

示例 3(应要求提供)

<?xml version='1.0' encoding='UTF-8' ?>

<ui:composition template="./WEB-INF/templates/base.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:c="http://java.sun.com/jsp/jstl/core">
    <ui:define name="content">
        <c:choose>
            <c:when test="#{webshop.productlist.size() > 0}">
                <div id="spacer">
                    <ui:repeat value="#{webshop.productlist}" var="product">
                        <div id="block">
                            <p>
                                <h:outputLink value="product.xhtml">
                                    #{product.name}
                                    <c:choose>
                                        <c:when test="#{product.category.parent.uri == null}">
                                            <f:param name="cat" value="#{product.category.uri}" rendered="" />
                                        </c:when>
                                        <c:otherwise>
                                            <f:param name="cat" value="#{product.category.parent.uri}" />
                                        </c:otherwise>
                                    </c:choose>
                                    <f:param name="product" value="#{product.uri}" />
                                </h:outputLink>
                            </p>
                        </div>
                    </ui:repeat>
                </div>
            </c:when>

            <c:otherwise>
                (...)
            </c:otherwise>
        </c:choose>
    </ui:define>
</ui:composition>

I have cleaned up this example a bit, but the essence is there. I have replaced the first examples by a when/otherwise construction, whether my product.category.parent.uri is null or not, it will give me the first result in this case.

我已经清理了这个例子,但本质就在那里。我已经用 when/otherwise 构造替换了第一个示例,无论我的 product.category.parent.uri 是否为空,在这种情况下它都会给我第一个结果。

回答by BalusC

Your core problem is that you're completely confusing view build time tags and view render time tags.

您的核心问题是您完全混淆了视图构建时间标签和视图渲染时间标签。

The view build time is that moment when a XHTML file is to be converted to a JSF component tree as available by FacesContext#getViewRoot(). The view render time is that moment when the JSF component tree is about to produce HTML code, as initiated by UIViewRoot#encodeAll().

视图构建时间是将 XHTML 文件转换为可用的 JSF 组件树的那一刻FacesContext#getViewRoot()。视图渲染时间是 JSF 组件树即将生成 HTML 代码的那一刻,由UIViewRoot#encodeAll().

All JSTL <c:xxx>tags and all JSF <ui:xxx>tags which do nothave a renderedattribute run during view build time. All JSF <ui:xxx>tags which dohave a renderedattribute and all JSF <h:xxx>tags run during view render time. So, they don't run in sync as you'd expect from the coding.

所有的JSTL<c:xxx>标签和所有JSF<ui:xxx>里面做标签具有rendered在视图生成时属性运行。所有的JSF<ui:xxx>标签来有一个rendered属性,所有的JSF<h:xxx>视图渲染时间期间运行的标签。因此,它们不会像您对编码所期望的那样同步运行。

Coming back to your concrete problem, this is two-fold:

回到你的具体问题,这是两方面的:

  1. The <f:param>does as being a tag handler not support the renderedattribute at all.

  2. The #{product}is in your code definied by <ui:repeat var>, which is a view render time tag, but yet you're trying to let JSTL <c:xxx>view build time tags depend on that. This will of course not work. The #{product}is nullduring the view build time, simply because the <ui:repeat>hasn't run at that moment.

  1. <f:param>不为标记处理程序不支持rendered的所有属性。

  2. #{product}是你的代码由definied <ui:repeat var>,这是一个视图渲染时间标记,但尚未你试图让JSTL<c:xxx>视图生成时间标签依赖于这一点。这当然行不通。这#{product}null在视图构建期间,仅仅是因为当时<ui:repeat>还没有运行。

Your concrete problem can only be solved by using the view build time tag <c:forEach>instead of the view render time tag <ui:repeat>to iterate over products.

您的具体问题只能通过使用视图构建时间标签<c:forEach>而不是视图渲染时间标签<ui:repeat>来迭代产品来解决。

<c:forEach items="#{webshop.productlist}" var="product">

See also

也可以看看



Unrelatedto the concrete problem, the follwing clumsy block

具体问题无关,下面的笨拙块

<c:choose>
    <c:when test="#{product.category.parent.uri == null}">
        <f:param name="cat" value="#{product.category.uri}" rendered="" />
    </c:when>
    <c:otherwise>
        <f:param name="cat" value="#{product.category.parent.uri}" />
    </c:otherwise>
</c:choose>

can be replaced by the following simpler approach with help of the conditional operator in EL:

在 EL 中的条件运算符的帮助下,可以用以下更简单的方法替换:

<f:param name="cat" value="#{empty product.category.parent.uri ? product.category.uri : product.category.parent.uri}" />

This way you must be able to keep using the <ui:repeat>.

这样,您必须能够继续使用<ui:repeat>.

回答by Bionic_Geek

According to the documentation, there is no renderedattribute available for the f:paramtag so it is being ignored.

根据文档,标签没有rendered可用的属性,f:param因此它被忽略。

See for JSF <2.x - http://docs.oracle.com/javaee/5/javaserverfaces/1.2/docs/tlddocs/f/param.html

请参阅 JSF <2.x - http://docs.oracle.com/javaee/5/javaserverfaces/1.2/docs/tlddocs/f/param.html

See for JSF >2.0 - http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/param.html

请参阅 JSF > 2.0 - http://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/f/param.html

Now that may suggest that example 2 should still work, so I might question whether or not product.category.parent.uriis really null as opposed to empty (i.e. blank string). Have you tried to test for empty (checks for null and empty string)?

现在这可能表明示例 2 应该仍然有效,所以我可能会质疑是否product.category.parent.uri真的为空而不是空(即空白字符串)。您是否尝试过测试是否为空(检查空字符串和空字符串)?

<c:if test="#{empty product.category.parent.uri}">  
<f:param name="cat" value="#{product.category.uri}" />  
</c:if>  

<c:if test="#{!empty product.category.parent.uri}">  
<f:param name="cat" value="#{product.category.parent.uri}" />
</c:if>

The other alternative, while not ideal, is to conditionally render two separate output links and determine which to render based on your value. Such as:

另一种选择虽然不理想,但有条件地呈现两个单独的输出链接,并根据您的值确定要呈现的内容。如:

<c:choose> 
  <c:when test="#{empty product.category.parent.uri}">
     <h:outputLink value="product.xhtml">
       <f:param name="cat" value="#{product.category.uri}"/>
       <f:param name="product" value="#{product.uri}" />
     </h:outputLink>
  </c:when>
  <c:otherwise>
     <h:outputLink value="product.xhtml">
        <f:param name="cat" value="#{product.category.parent.uri}" />
        <f:param name="product" value="#{product.uri}" />
     </h:outputLink>
  </c:otherwise>
</c:choose>