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

TCM*_*TCM 32 jsf facelets postconstruct view-scope

我在页面上使用datatable并使用绑定属性将其绑定到我的支持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>
Run Code Online (Sandbox Code Playgroud)

这是我的豆子: -

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!!");

    }
}
Run Code Online (Sandbox Code Playgroud)

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

Bal*_*usC 33

有趣的是,当您在视图范围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>
Run Code Online (Sandbox Code Playgroud)

也可以看看:


更新(2012年12月):这确实是JSF2中的一个错误.这是一个鸡蛋问题.视图范围bean存储在JSF视图状态中.因此视图范围bean仅在还原视图阶段后可用.但是,该binding属性在还原视图阶段运行,而视图范围Bean尚不可用.这会导致创建一个全新的视图范围bean实例,然后由实际视图范围bean替换,该实例存储在已恢复的JSF视图状态中.

这被报告为JSF问题1492JSF规范isssue 787,将为JSF 2.2修复.在此之前,您最好的选择是binding专门使用请求范围的bean,或者寻找特定功能需求的替代方法.


更新(2015年3月):JSF 2.2修复程序被移植到Mojarra 2.1.18.因此,如果您仍在使用JSF 2.0/2.1,则最好升级到至少该版本.另请参见ao JSF中的组件绑定是什么?何时优先使用?JSF2 Facelets中的JSTL ......有意义吗?

  • 1)这是JSF 1.x的遗留物.2)是的.只需`getRowData()`in action方法将为您提供调用操作的行. (3认同)
  • 嗨BalusC,我读了你关于ViewScoped的文章以及阅读这篇文章.我有两个问题要问你.第一:为什么人们将表绑定到托管bean.在这个例子中,我认为他提到绑定dataTable来初始化它的值,但是你可以在@PostConstruct中初始化一个对象列表,并在dataTable中显示它们.这不会达到同样的结果吗?其次:在你的项目中,你使用了DataModel,所以如果你包装对象列表,你想在dataTable中显示,在DataModel中,那么无论用户选择哪一行,你都会知道你是否调用了getRowData()? (2认同)

归档时间:

查看次数:

24992 次

最近记录:

10 年,2 月 前