com.sun.faces.numberOfViewsInSession 与 com.sun.faces.numberOfLogicalViews

Posted

技术标签:

【中文标题】com.sun.faces.numberOfViewsInSession 与 com.sun.faces.numberOfLogicalViews【英文标题】:com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews 【发布时间】:2011-05-05 13:29:07 【问题描述】:

JSF 2 的 Mojarra 实现具有以下上下文参数:

com.sun.faces.numberOfViewsInSession(默认为 15) com.sun.faces.numberOfLogicalViews(默认为 15)

它们之间有什么区别?文档并没有过多地谈论这些。我的应用在某些页面上遇到了ViewExpiredException 的问题,但在我们将这些设置提高到(高得多)的值后,问题就停止了。

我的应用是一个财务、表单繁重、支持 ajax 的应用(有些屏幕有 50 多个输入,可以选择通过 AJAX 添加更多数据/输入)。

这种行为的原因可能是什么?我知道第一个参数定义了会话中保留的“页面”数量,这可能对后退按钮有用,但我触发ViewExpiredException 的用例不使用后退按钮。第二个参数指的是什么?如果我停留在同一个屏幕,但通过 AJAX 继续添加大量数据,这是否会导致页面需要大量逻辑视图?

【问题讨论】:

【参考方案1】:

首先,Mojarra 实现无意中交换了这些上下文参数的含义。因此,如果您认为描述与字面上下文参数名称所暗示的完全相反,那么这确实是正确的。


com.sun.faces.numberOfLogicalViews

这基本上是基于 GET 请求的。每个 GET 请求都会在会话中创建一个新视图。

要进行实验,请将其设置为 3,启动一个新的浏览器会话并依次打开 4 个不同的浏览器选项卡(无论 URL;可能相同,可能不同),然后返回第一个标签并在那里提交表格。您将获得ViewExpiredException,因为该视图已从 LRU(最近最少使用)地图中推出,用于会话中的视图。如果您最多打开 3 个标签,则不会发生这种情况。

默认值为 15,这是一个罕见的现实问题。如果您的 web 应用程序确实设计为以这种方式使用(例如,邀请在多个选项卡中打开的社交/社区站点,例如讨论论坛或问答),那么您可能会考虑使用客户端状态保存而不是增加默认值.使用客户端状态保存,您将永远不会遇到此异常。另一种方法是结合使用OmniFaces <o:enableRestorableView> 请求范围的bean 和请求参数,或者如果需要恢复其自身的状态,则在(后)构造中签入的视图范围的bean。另一种选择是去stateless with <f:view transient="true">,这样视图就不再保存了,但是你不能再使用视图范围的bean了。

MyFaces 等效值为 org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION,默认为 20。


com.sun.faces.numberOfViewsInSession

这基本上是基于同步(非 ajax!)POST 请求的。每个同步 POST 请求都会创建一个新的逻辑视图。它们都是基于物理视图存储的,例如Map<PhysicalView, Map<LogicalView, ViewState>>。因此,最多 15 个物理视图和最多 15 个逻辑视图,理论上您可以在会话中拥有 15*15 = 225 个视图。

要试验一下,将其设置为 3,打开一个同步表单的视图,提交 4 次,然后按浏览器的后退按钮 4 次,然后再次提交表单。您将获得ViewExpiredException,因为该视图已从逻辑视图的 LRU(最近最少使用)映射中推出。如果您最多返回 3 次然后重新提交,则不会发生这种情况。

请注意,ajax 提交重用了相同的逻辑视图(您可以通过查看在 ajax 回发上返回的完全相同的 javax.faces.ViewState 值来确认它)。无论如何,没有浏览器的后退按钮支持。浏览器的后退按钮只会让您回到之前的同步请求,因此将所有这些 ajax 回发存储为会话中的逻辑视图是没有任何意义的。

在默认值 15 以及当前的仅 ajax 表单趋势和动态页面上禁用缓存的情况下,这是一个非常罕见的现实世界问题。正确设计的表单不应邀请按下浏览器的后退按钮。相反,他们应该成功提交重定向到目标视图,失败时只需重新显示带有验证错误的相同表单。另请参阅How to navigate in JSF? How to make URL reflect current page (and not previous one) 以获取提示。此外,缓存在动态页面上经常被禁用,所以返回按钮基本上会给你一个全新的视图。另见Avoid back button on JSF web application。如果这也适用于您的应用程序的情况,那么您可以放心地将值设置为 1。

MyFaces 最初对此没有等效项,并将其视为会话中的物理视图。在 2.0.6 版中,引入了 org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION,目的相似,但实现方式不同且默认禁用。


另见:

Why JSF saves the state of UI components on server? Should PARTIAL_STATE_SAVING be set to false? javax.faces.application.ViewExpiredException: View could not be restored What is the usefulness of statelessness in JSF?

【讨论】:

@BalusC:你的意思是 JSF Mojarra 可以为每个逻辑视图存储 15 个物理视图,其中一个物理视图包含多个表单。 @Shirgill:每个物理视图有 15 个物理视图和 15 个逻辑视图。这与表单的数量无关(您可以通过在 javax.faces.ViewState 隐藏字段中看到它们都具有相同的值来确认)。 @BalusC:实际上,就像 ZEEF 这样的网站一样,如果我通过打开 16 个选项卡触发 16 个 GET 请求,然后过来,它的 javax.faces.STATE_SAVING_METHOD 设置为服务器到第一个选项卡并通过按命令按钮提交内容,如果 com.sun.faces.numberOfLogicalViews 为 15,则会发生 viewexpiredexcetion。为什么选择服务器作为状态保存端? @BalusC:这与您上面的答案部分有关-并在上面提到-如果您的网络应用程序确实设计为以这种方式使用(例如,邀请打开的社交/社区网站在多个选项卡中,例如论坛或问答),那么您可以考虑使用客户端状态保存 @Shirgill:ZEEF 的表单太多,无法有效地保存客户端状态。 ZEEF 使用 OmniFaces <o:enableRestorableView>@ViewScoped(卸载感知)。【参考方案2】:

刚刚在网上找到这个:http://oss.org.cn/ossdocs/java/ee/javaeetutorial5/doc/JSFConfigure11.html

这可能会有所帮助:

逻辑视图是***视图的子视图。例如,如果您有一个包含多个框架的页面,那么每个框架都是一个逻辑视图。 如果您有一个简单的应用程序,那么默认的 15 个视图或 15 个逻辑视图可能会太大。在这种情况下,您应该考虑减少允许的视图和逻辑视图数量以节省内存。相反,更复杂的应用程序可能需要在会话中保存超过 15 个视图或逻辑视图。

【讨论】:

以上是关于com.sun.faces.numberOfViewsInSession 与 com.sun.faces.numberOfLogicalViews的主要内容,如果未能解决你的问题,请参考以下文章