未使用 URL 参数时在 POST 上重新创建视图范围的 bean

Posted

技术标签:

【中文标题】未使用 URL 参数时在 POST 上重新创建视图范围的 bean【英文标题】:View-scoped bean recreated on POST when URL parameters not used 【发布时间】:2012-12-22 07:30:08 【问题描述】:

我有一个 view-scoped JSF 管理的 bean,它支持 xhtml 视图,我使用 f:viewParam从 URL 读取一个参数>.

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

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

代码如下:

查看

<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>

支持 bean

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

更新

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

【问题讨论】:

此行为是设计使然。此问题可能与以下问题重复:***.com/questions/10352641/… @elias:这不是同一个问题。 Marcus,@ManagedProperty 放错地方了,我会摆脱它。至于具体问题,请显示最小可能的视图sn-p,它仅通过复制粘贴即可重现此问题。当您将标记处理程序属性(例如&lt;c:if&gt;&lt;ui:include&gt; 等)绑定到它的属性时,将重新创建视图范围 bean,但这在到目前为止发布的代码中不可见,这似乎过于简单化了.您需要准确地提供所需的信息,以便在完全空白项目上重现问题,并将所有内容设置为默认值,也可以由您自己进行。 @BalusC 你是对的!我匆忙阅读并被新近效应所吸引。 @BalusC 我确实同时使用了 。我将删除它们以查看 bean 是否被重新创建,并将跟进调查结果。 【参考方案1】:

这个问题在目前发布的代码中是不可见的,但是对于 JSF 2.0/2.1 来说,一个已知的问题是,当一个视图范围的 bean 的一个属性被绑定到像 JSTL @ 这样的标记处理程序的一个属性时,将重新创建一个视图范围的 bean 987654323@ 或 Facelets &lt;ui:include&gt; 或 JSF 组件的视图构建时间属性,例如 idbinding,同时启用部分状态保存(默认情况下)。

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

基本上有3种解决方案:

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

另见:

JSTL in JSF2 Facelets... makes sense? @ViewScoped fails in taghandlers

【讨论】:

虽然这个解决方案没有解决我遇到的确切问题(我只是使用已知错误的旧版本 Mojarra),但这个答案向我展示了一些我能够做到的新概念用于解决我们项目遇到的其他问题。非常感谢,BalusC!

以上是关于未使用 URL 参数时在 POST 上重新创建视图范围的 bean的主要内容,如果未能解决你的问题,请参考以下文章

动画视图控制器并同时在表格视图中重新加载数据

使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean

Django 创建多个 URL,为 POST 和 GET 调用相同的视图

搜索时在字符类型上创建 url 请求的好方法

如何在 Laravel-8 和 InertiaJs 中向服务器发出 POST 请求时在浏览器中保留当前的 ​​GET url

允许在从 UI 端进行 Post 请求时在 url 中发送特殊字符