我偶然发现了一个 JSF / PrimeFaces 问题,虽然我设法通过改变支持bean的范围来实现它,我仍然想知道为什么它在第一种情况下失败了 . 所以,这是一个缩小的例子,它重现了这种行为:

我们有一个简单的 xhtml 页面,它在一个表单中显示两个 p:dataTables ,一个在另一个下面 . 顶部 p:dataTable 显示数字,第二个显示其除数 . 所以我们有一个经典的主 - 细节视图 . 一个按钮允许我们更新页面,所以当从顶部表格中选择一个新的数字时,我们可以在底部表格中查看它的除数:

<h:form id="NUMBERS-form">
    <p:dataTable id="dt1" var="item" value="#{numbersController.divisorSets}"
                 rowKey="#{item}" rows="10" selection="#{numbersController.selectedDivisorSet}"
                 selectionMode="single">
        <p:column>
            #{item}
        </p:column>
    </p:dataTable>

    <p:dataTable id="dt2" var="item" value="#{numbersController.divisors}"
                 rowKey="#{item}" rows="10" selection="#{numbersController.selectedDivisor}"
                 selectionMode="single">
        <p:column id>
            #{item}
        </p:column>
    </p:dataTable>
    <p:commandButton id="Update"     ajax="true" update=":NUMBERS-form"
                     action="#{numbersController.foo}" value="update"/>
</h:form>

backing bean定义了两个只读集合:一个用于DivisorSets(即我们想要查找其除数的数字),另一个用于当前所选数字的除数 . 它还有两个字段和属性getter / setter,用于当前选定的数字和当前选定的该数字的除数:

@ManagedBean
@ViewScoped // if this is toggled to @RequestScoped it stops working
public class NumbersController implements Serializable {
    private static final Logger l = Logger.getLogger(NumbersController.class.getName());

    public List<DivisorSet> getDivisorSets() {
        List<DivisorSet> retValue = new ArrayList<DivisorSet>();
        for (int i = 10 ; i < 20 ; i++)
            retValue.add( new DivisorSet(i) );
        return retValue;
    }

    public List<Integer> getDivisors() {
        if (selectedDivisorSet != null)
            return selectedDivisorSet.getDivisors();
        else return null;
    }

    private DivisorSet    selectedDivisorSet;
    // getter and setter ...

    private Integer   selectedDivisor;
    // getter and setter ...

    public String foo() { return null; }
}

首次加载页面时,仅填充顶部 p:dataTable . 当选择顶部表格的一行并按下 p:commandButton 时,该数字的除数将在底部 p:dataTable 上获取 . 到现在为止还挺好 . 问题出现了:当从顶部表中选择一行并且从底部表中选择一行并按下 p:commandButton 时,我在setter中的日志消息显示:

  • 当支持bean的范围设置为 View 时,在 update model values 阶段中正确设置了所选数字

  • 当支持bean的范围设置为 Request 时,只有顶层表中的选定数字设置正确, selectedDivisor 字段的setter(与底部 p:dataTable 链接)的值为0(或其他示例中为null)我尝试过使用不同的类) .

请注意,在这个简单的示例中没有业务逻辑可以从底部选择一个数字 p:dataTable - 这只是我在真实环境中遇到的同一问题的缩小版本 . 任何人都可以解释JSF生命周期中导致底部表选择值在视图为 RequestScoped (而不是成功的 ViewScoped )时未正确设置的步骤吗?