【问题标题】:JSTL c:forEach causes @ViewScoped bean to invoke @PostConstruct on every requestJSTL c:forEach 导致 @ViewScoped bean 在每个请求上调用 @PostConstruct
【发布时间】:2011-02-20 00:10:53
【问题描述】:

我再次看到@PostConstruct 每次都在触发,即使没有使用绑定属性。请参阅此代码:-

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <c:forEach var="item" items="#{TestBean.listItems}">
                <h:outputText value="#{item}"/>
            </c:forEach>
            <h:commandButton value="Click" actionListener="#{TestBean.actionListener}"/>
        </h:form>
    </h:body>
</html>

这是 JSF 中最简单的 bean:-

package managedBeans;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean(name="TestBean")
@ViewScoped
public class TestBean implements Serializable {

    private List<String> listItems;

    public List<String> getListItems() {
        return listItems;
    }

    public void setListItems(List<String> listItems) {
        this.listItems = listItems;
    }

    public TestBean() {

    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!");
        listItems = new ArrayList<String>();
        listItems.add("Mango");
        listItems.add("Apple");
        listItems.add("Banana");
    }

    public void actionListener(){
        System.out.println("Action Listener fired!");
    }

}

您是否发现任何会导致每次都触发 postconstruct 回调的行为?我认为 JSF 2.0 非常不稳定。如果每次都必须触发 PostConstruct,@ViewScoped 的作用是什么。为什么不只使用@RequestScoped?我以为我在申请中犯了一些错误。但是当我在 JSF 中创建这个最简单的可能时,我仍然得到这个错误。我不了解 JSF 的范围吗?还是他们没有正确测试?此外,如果您删除 c:forEach 并将其替换为 ui:repeat,则它可以正常工作。

等待回复确认是bug还是故意阻止程序员使用jstl?

【问题讨论】:

    标签: java jsf jstl facelets


    【解决方案1】:

    此问题与您之前在此处回答的问题具有相同的理由:Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF

    这确实是 JSF2 中的一个错误。这是一个鸡蛋问题。视图范围的 bean 存储在 JSF 视图状态中。因此视图范围的 bean 仅在恢复视图阶段后可用。但是,JSTL 标记在恢复视图阶段运行,而视图范围的 bean 尚不可用。这会导致创建一个全新的视图范围 bean 实例,然后将其替换为存储在恢复的 JSF 视图状态中的真实视图范围 bean。

    这被报告为 JSF issue 1665JSF spec isssue 787,它们已为 JSF 2.2 修复并移植回 Mojarra 2.1.18。因此,只需至少升级到 Mojarra 2.1.18 即可。

    如果您无法升级,那么最好的办法是在请求/会话/应用程序范围的 bean 上专门使用 JSTL 标记,或者为特定的功能需求寻找替代方法。正如您已经发现的那样,您可以将 &lt;c:forEach&gt; 替换为 &lt;ui:repeat&gt;

    另见:

    【讨论】:

    • 好的,谢谢 BalusC。我认为这也只是错误。 jstl 与@PostConstruct 有什么关系。无论如何,我将用 ui:repeat 替换它。
    • 嘿BalusC。如果您为此创建问题,请给我链接:)。所以我可以向我的大学朋友展示我在 JSF 2.0 中发现的错误:
    • 谢谢:)。它仍然未经证实。实际上,两者的状态都未经证实。不知道他们什么时候会检查。
    • @BalusC 更新了问题的链接@@java.net/jira/browse/JAVASERVERFACES-1665
    猜你喜欢
    • 2014-03-21
    • 2015-12-03
    • 2011-07-29
    • 2014-10-17
    • 1970-01-01
    • 2011-04-20
    • 2012-10-16
    相关资源
    最近更新 更多