Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么即使bean是@viewscope的,@PostConstruct回调每次都会触发?JSF_Jsf_Facelets_View Scope_Postconstruct - Fatal编程技术网

为什么即使bean是@viewscope的,@PostConstruct回调每次都会触发?JSF

为什么即使bean是@viewscope的,@PostConstruct回调每次都会触发?JSF,jsf,facelets,view-scope,postconstruct,Jsf,Facelets,View Scope,Postconstruct,我在页面上使用datatable,并使用binding属性将其绑定到我的支持bean。这是我的代码:- <?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://w

我在页面上使用datatable,并使用binding属性将其绑定到我的支持bean。这是我的代码:-

<?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:p="http://primefaces.prime.com.tr/ui">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
            <h:form prependId="false">

                <h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
                    <h:column>
                        <h:outputText value="#{item}"/>
                    </h:column>
                    <h:column>
                        <h:commandButton value="Click" actionListener="#{testBean.action}"/>
                    </h:column>
                </h:dataTable>

            </h:form>

    </h:body>
</html>

Facelet标题
这是我的豆子:-

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;
import javax.faces.component.html.HtmlDataTable;

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

    private List<String> stringCollection;

    public List<String> getStringCollection() {
        return stringCollection;
    }

    public void setStringCollection(List<String> stringCollection) {
        this.stringCollection = stringCollection;
    }

    private HtmlDataTable dataTable;

    public HtmlDataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(HtmlDataTable dataTable) {
        this.dataTable = dataTable;
    }

    @PostConstruct
    public void init(){
        System.out.println("Post Construct fired!!");
        stringCollection = new ArrayList<String>();
        stringCollection.add("a");
        stringCollection.add("b");
        stringCollection.add("c");

    }

    public void action(){
        System.out.println("Clicked!!");

    }
}
packagemanagedbeans;
导入java.io.Serializable;
导入java.util.ArrayList;
导入java.util.List;
导入javax.annotation.PostConstruct;
导入javax.faces.bean.ManagedBean;
导入javax.faces.bean.ViewScoped;
导入javax.faces.component.html.HtmlDataTable;
@ManagedBean(name=“testBean”)
@视域
公共类testBean实现了可序列化{
私人收藏;
公共列表getStringCollection(){
回收;
}
公共作废setStringCollection(列表stringCollection){
this.stringCollection=stringCollection;
}
私有HtmlDataTable数据表;
公共HtmlDataTable getDataTable(){
返回数据表;
}
公共void setDataTable(HtmlDataTable数据表){
this.dataTable=dataTable;
}
@施工后
公共void init(){
System.out.println(“Post-Construct-fired!!”;
stringCollection=新的ArrayList();
stringCollection.添加(“a”);
(b)添加(“b”);
(c)添加(“c”);
}
公共无效行动(){
System.out.println(“单击!!”;
}
}

请告诉我为什么每次我点击按钮,@PostConstruct都会启动?只要我在同一页面上,它应该只触发一次,因为我的bean是@viewscope。此外,如果我删除binding属性,那么一切都正常,@PostConstruct回调只触发一次。那么为什么每次我都使用binding属性呢?我需要binding属性,并希望只执行一次初始化任务,如从webservice获取数据等。我该怎么办?我应该在哪里写我的初始化任务?

有趣的是,当您在视图范围的bean上使用组件绑定时,视图范围会中断

我不确定这是否是JSF2中的错误,我必须先阅读整个JSF2规范。到目前为止,最好的办法是暂时放弃组件绑定,并通过新的EL 2.2方法参数语法传递所选项:

<h:dataTable var="item" value="#{testBean.stringCollection}">
    <h:column>
        <h:outputText value="#{item}"/>
    </h:column>
    <h:column>
        <h:commandButton value="Click" action="#{testBean.action(item)}"/>
    </h:column>
</h:dataTable>

另见:

更新(2012年12月):这确实是JSF2中的一个bug。这是个鸡蛋问题。视图范围的bean存储在JSF视图状态中。因此,视图范围的bean只有在恢复视图阶段之后才可用。但是,
绑定
属性在恢复视图阶段运行,而视图范围的bean还不可用。这导致创建一个全新的视图范围bean实例,该实例随后被存储在恢复的JSF视图状态中的真实视图范围bean所取代

这被报告为,并将在JSF2.2中修复。在此之前,您最好的选择是专门在请求范围内的bean上使用
绑定
,或者为特定的功能需求寻找替代方法



更新(2015年3月):JSF2.2补丁被后移植到Mojarra 2.1.18。因此,如果您仍在使用JSF2.0/2.1,最好至少升级到该版本。另请参见a.o.和

,正如其他人所说,我认为最好的办法是放弃组件绑定(这里不需要它)

但我要补充的是,通过使用动作参数,您可以以更面向对象的方式实现同样的效果,如下所示:

<h:commandButton value="Click" action="#{testBean.action(item)}"/>

如果您有一个viewscoped bean,并且希望保留表单上输入的值,或者不希望触发postconstruct,那么应该从操作方法返回null

如果返回某个结果(例如无效),然后使用faces-config.xml将无效结果指向同一页面,则ViewScope bean将被重新创建,从而导致postconstruct再次启动

其他解决方案:

  • 在请求范围bean中绑定HtmlDataTable
  • 将这个请求范围bean注入到视图范围bean中

JBoss Seam使用此解决方案将JSF组件绑定到对话范围组件。

balusc的回答对我帮助很大,我想说的是,我在mojarra 2.1.7版中遇到了这个错误,我目前使用的是2015年1月发布的2.1.29-01,这个错误已经修复,我的问题是将tabview绑定到viewscoped bean。在这个版本中,我没有那个bug,绑定和后期构造工作正常。 我使用Jboss 5.2,我必须使用mojarra 2.1.x,所以我希望这个答案能帮助其他处于同样情况的人


JSF规范没有提到这一点。我已经存档了。顺便说一下,我现在可以重现您的问题,即每次只返回第一个项目。我在我的环境中犯了一个错误,相同的bean已经在faces-config.xml中声明为请求范围,它已经覆盖了注释。Hmm!:)那么这也是一个错误吗?关于datatable?请参阅更新的答案,
DataModel 35; getRowData()
是一个更好的选择。嗨,巴卢斯克,我读了你关于ViewScoped的文章,也读了这篇文章。我有两个问题要问你。第一:为什么人们要将表绑定到托管bean。在这个例子中,我想他提到了绑定dataTable来初始化它的值,但是您可以在@PostConstruct中初始化一个对象列表,并在dataTable中显示它们。这难道不会达到同样的结果吗?第二:在您的项目中,您使用了DataModel,因此如果您将要在dataTable中显示的对象列表包装在DataModel中,那么无论用户选择哪一行,您都会知道是否调用getRowData()?1)这是JSF 1.x的遗留内容。2) 对。只需
getRowData(
  public void action(Item item){
    System.out.println("Clicked!!" + item);
}