6

我有一个视图范围的JSF 托管 bean,它支持一个xhtml视图,我使用f:viewParam从 URL 读取一个参数。

视图向用户呈现一个表单。但是,当用户通过按下p:commandButton提交表单时,似乎重新创建了视图范围的 bean(我添加了一个@PostConstruct注释来验证这一点),因此不记得从f:viewParam读取的实例变量(下面代码中的invId)。

我最初使用包含URL参数的GET导航到视图,但是当用户按下p:commandButton时发送的POST消息不包含URL参数。所以我在想,当 JSF 运行时在POST上看不到 URL 参数时,它认为这是一个不同的视图,并且正在重新创建 JSF 管理的 bean。当我将视图范围更改为会话范围时,代码有效。

这是代码:

看法

<f:metadata>
    <f:viewParam name="invId" value="#{registerBean.invId}"/>
</f:metadata>
<h:form id="registrationForm">
     ....
    <p:commandButton value="register" action="#{registerBean.register}"
                     icon="ui-icon ui-icon-newwin" ajax="false"/>
</h:form>

后备豆

@ManagedBean                                      
@ViewScoped
public class RegisterBean implements Serializable {
    @ManagedProperty(value="#{invId}")
    private String invId;
    ...

更新

事实证明,这根本与 URL 参数无关。按照下面的BalusC建议,我删除了我的视图使用的c:when标记(依赖渲染属性而不是相同的效果),现在不再重新创建视图范围的 bean,并且正确保留了invId字段。

4

1 回答 1

8

该问题在到目前为止发布的代码中不可见,但对于 JSF 2.0/2.1 而言,这是一个已知问题,即当视图范围 bean 的一个属性绑定到标记处理程序(如 JSTL<c:if>或 Facelets<ui:include>或查看 JSF 组件的构建时间属性,例如idbinding,同时启用部分状态保存(默认情况下)。

背景解释是这些属性中的任何 EL 表达式都是在构建和恢复视图期间执行的。由于视图范围 bean 存储在视图中,因此只有恢复视图后才可用,因此这样的 EL 表达式评估将导致创建一个全新且单独的视图范围 bean。这基本上是一个鸡蛋问题。它在即将到来的 JSF 2.2 中得到修复。

基本上有3种解决方案:

  1. 相应地更改视图,以便仅在视图渲染期间评估这些 EL 表达式。例如替换<c:if>/ <c:choose>rendered
  2. 或者将这些属性绑定到请求范围 bean(设计注意事项:您可以将视图范围 bean 作为请求范围 bean 的托管属性注入)。
  3. 如果需要,仅对特定视图关闭部分状态保存。

也可以看看:

于 2013-01-08T14:21:09.827 回答