【问题标题】:JSF: bean scope; session vs requestJSF:bean作用域;会话与请求
【发布时间】:2011-06-15 22:43:23
【问题描述】:

我有一个名为 UserSearchHandler 的托管 bean,它有一个填充 UserSearchHandler.searchResultsdoSearch 方法,这些方法显示在 userSearch.xhtml 页面上的表格中。

我有另一个名为 UserHandler 的托管 bean,它有一个 showUser 方法等等。

在搜索结果表中,用户名是一个链接,当单击该链接时,应该会在userView.xhtml 页面上显示用户详细信息。表格和链接如下所示:

<p:dataTable var="user" value="#{userSearchHandler.searchResults" >

// ... and so on ... then

<h:commandLink value="#{user.firstName}" action="#{userHandler.showUser}">
  <f:setPropertyActionListener target="#{userHandler.userIdToShow}" value="#{profile.id}"/>
</h:commandLink>

当托管 bean 设置为 session 范围时,一切正常。

但是,当我将 bean 上的范围更改为 request 时,搜索工作并且表格被填充,但是当我单击名称链接时没有任何反应。我在userHandler.showUser 方法上设置了一个断点,当userSearchHandler 设置为“请求”范围时,它永远不会被击中。

谁能帮助解释这是为什么,或者我做错了什么?

【问题讨论】:

    标签: jsf


    【解决方案1】:

    我有几个想法。如果您在导航中使用 a,您可以尝试将其删除。这样做意味着浏览器在呈现第二个窗口时不会发出新的 HTTP 请求。它是清除请求范围 bean 的新 HTTP 请求。如果这不是一个选项,您可以在链接中传递一个参数,例如记录 ID,这可以让您从与该 ID 匹配的数据源中提取数据。

    【讨论】:

    • 除非您添加了&lt;redirect/&gt;,否则导航默认不会触发新请求。它只是在幕后使用RequestDispatcher#forward()。负责新请求的是表单提交(按下commandlink/commandbutton的纯客户端交互)。
    • 我用 lt 和 gt 胡萝卜输入了 redirect/,但它没有出现在我的答案中。对于那个很抱歉。这就是我想说的。我不知道是否使用了重定向。我在 JavaServer Faces 2.0 The Complete Reference 中读到,按下没有带有重定向的导航规则或不包含 ?faces-redirect=true 的隐式导航的命令按钮/链接将简单地发布表单值,而无需浏览器制作对新 URL 的第二个 HTTP 请求。
    • 相反,浏览器将简单地呈现新页面,并且请求范围 bean 中的值仍然可用。但是我比较新,所以很可能我误解了我所读的内容。我会去重读。
    【解决方案2】:

    这是因为 #{userSearchHandler.searchResults} 在新请求期间为空,因此 JSF 无法找到调用 commandlink 以调用操作的关联行(以及传递/设置属性,如果有的话)。

    您需要确保在 bean 的构造/初始化期间预先创建了相同的 #{userSearchHandler.searchResults}。如果要根据一组特定的参数创建它,那么您也必须将它们与表单一起传递。

    这正是像 Tomahawk 的 &lt;t:saveState /&gt; 和新的 JSF 2.0 视图范围这样的解决方案存在的原因。

    另见:

    【讨论】:

    • 谢谢!有没有办法让它在不使 UserSearchHandle 成为会话范围的 bean 的情况下工作?
    • 如果您使用的是 JSF 2.0,只需将 bean 放在视图范围内。如果您仍在使用 JSF 1.x,请考虑 Tomahawk 的 t:saveState(不确定 PrimeFaces 是否为此提供类似的内部解决方案,我从未在 JSF 1.x 上使用过 PrimeFaces)。
    • 再次感谢。我正在使用 JSF2。更多问题。 :) 阅读有关视图范围的信息,在我的情况下,我正在单击加载一个新页面“userView.xhtml”。将查看范围在这里工作还是我应该留在同一页面上工作?另外我正在使用 Spring IoC,因此我使用 Spring 注释来创建托管 bean,例如“@Scope("session")”,并且那里似乎没有“@Scope("view")”选项.
    • 啊春天,到此为止。要么用 Java EE 6 CDI 替换 Spring(如果您运行 Java EE 6 容器),要么采用 Tomahawk 方法。非常简单:安装必要的 jar 包后,在页面中添加 &lt;t:saveState value="#{userSearchHandler}" /&gt;。而已。它的行为与视图范围完全相同(在您的情况下,它本来可以工作,是的,无论如何提交都会返回到同一个视图)。
    • 更多细节——还有另一个问题——我将托管 bean 中的 Spring 注释更改为 JSF2 注释;前任。 "@Scope("session")" 变成了 "@SessionScoped" 等等。我让应用程序再次工作(使用会话范围的 bean)。然后我将@SessionScoped 更改为@ViewScoped,当它运行时我收到一个错误,即我的处理程序UserSearchHandler 不可序列化。我添加了“实现可序列化”,然后我收到一个错误,即存在不可序列化的 Spring 和/或 Hibernate 类。这个“可序列化”错误是我可以修复的,还是我做错了什么?
    猜你喜欢
    • 2017-03-12
    • 2017-08-02
    • 1970-01-01
    • 2020-07-01
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    相关资源
    最近更新 更多