JSTL c:forEach导致@ViewScoped bean在每个请求上调用@PostConstruct [英] JSTL c:forEach causes @ViewScoped bean to invoke @PostConstruct on every request

查看:153
本文介绍了JSTL c:forEach导致@ViewScoped bean在每个请求上调用@PostConstruct的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Again i see that the @PostConstruct is firing every time even though no binding attribute is used. See this code :-

<?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: -

And this is the simplest possible bean in JSF :-

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非常不稳定。如果每次@ViewScoped服务的目的都必须触发PostConstruct。为什么不只使用@RequestScoped?我以为我在申请中犯了一些错误。但是当我在JSF中创建这个最简单的时候,我仍然会遇到这个错误。我不理解JSF的范围?或者他们没有正确测试?此外,如果你删除c:forEach并用ui:repeat替换它,那么它工作正常。

Do you see any behaviour that should cause postconstruct callback to fire each time? I think JSF 2.0 is highly unstable. If it has to fire PostConstruct each and every time what purpose does @ViewScoped serve. Why not to use @RequestScoped only? I thought i have made some mistake in my application. But when i created this simplest possible in JSF, i still get this error. Am i not understanding the scopes of JSF? or are they not testing it properly? Further, if you remove c:forEach and replace it with ui:repeat, then it works fine.

等待回复以确认它是否是错误或是故意的阻止程序员使用jstl?

Waiting for replies to confirm whether it is bug or it is intentional to stop the programmers from using jstl?

推荐答案

此问题与您之前回答的问题具有相同的理由:为什么@PostConstruct回调会触发每个时间即使bean是@ViewScoped? JSF

This problem has the same grounds as your previous question which is answered here: Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF.

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

This is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, JSTL tags runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.

这是报告为 JSF issue 1665 JSF spec isssue 787 ,它已针对JSF 2.2修复并移植回Mojarra 2.1.18。所以,只需升级到Mojarra 2.1.18即可。

This is reported as JSF issue 1665 and JSF spec isssue 787 which is fixed for JSF 2.2 and ported back in Mojarra 2.1.18. So, just upgrading to a minimum of Mojarra 2.1.18 should do.

如果你无法升级,那么最好的办法是在请求/会话中使用JSTL标签/ application scoped beans exclusive,或寻找特定功能需求的替代方法。您可以使用< ui:repeat> 替换< c:forEach> ,如您所知。

If you can't upgrade, then your best bet is to use JSTL tags on request/session/application scoped beans exclusively, or to look for alternate ways for the particular functional requirement. You can replace the <c:forEach> with <ui:repeat> as you already found out.

  • Communication in JSF 2.0 - @ViewScoped fails in taghandlers
  • JSTL in JSF2 Facelets... makes sense?

这篇关于JSTL c:forEach导致@ViewScoped bean在每个请求上调用@PostConstruct的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆