32

我在页面上使用数据表并使用绑定属性将其绑定到我的支持 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>

这是我的豆子:-

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

    }
}

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

4

5 回答 5

34

有趣的是,当您在视图范围的 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 中的一个错误。这是一个鸡蛋问题。视图范围的 bean 存储在 JSF 视图状态中。因此视图范围的 bean 仅在恢复视图阶段后可用。但是,该binding属性在恢复视图阶段运行,而视图范围的 bean 尚不可用。这会导致创建一个全新的视图范围 bean 实例,然后将其替换为存储在恢复的 JSF 视图状态中的真实视图范围 bean。

这被报告为JSF 问题 1492JSF 规范问题 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... 有意义吗?

于 2010-05-09T16:37:42.010 回答
4

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

但我要补充一点,您可以通过使用操作参数以更面向对象的方式实现与您尝试相同的效果,如下所示:

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

...在你的java代码中:

  public void action(Item item){
    System.out.println("Clicked!!" + item);
}
于 2011-03-16T15:10:16.787 回答
0

其他解决方案:

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

JBoss Seam 使用这个解决方案将 JSF 组件绑定到会话范围组件。

于 2013-05-16T15:50:49.710 回答
0

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

http://mvnrepository.com/artifact/com.sun.faces/jsf-api/2.1.29-01 http://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-01

于 2015-03-20T12:54:40.537 回答
0

如果你有一个 viewscoped bean,并且你想保留在表单上输入的值或者不想触发 postconstruct,你应该从你的 action 方法中返回 null。

如果您返回一些结果(例如无效),然后使用 faces-config.xml 将无效结果指向同一页面,那么 viewscoped bean 将被重新创建,从而导致 postconstruct 再次触发。

于 2013-03-26T17:20:53.753 回答