com.sun.faces.numberOfViewsInSession与com.sun.faces.numberOfLogicalViews的区别是什么?

37
Mojarra JSF 2的实现具有以下上下文参数:
  • com.sun.faces.numberOfViewsInSession(默认值为15)
  • com.sun.faces.numberOfLogicalViews(默认值为15)
它们之间有什么区别?文档对此没有过多解释。我的应用程序在某些页面出现ViewExpiredException问题,但是在我们将这些设置提高到(更高的)值后,问题得到了解决。
我的应用程序是一个财务、表单重型、启用AJAX的应用程序(一些屏幕具有50多个输入,并且可以通过AJAX添加大量更多数据/输入选项)。
这种行为的原因是什么?我知道第一个参数定义了在会话中保留的“页面”数,这对于返回按钮可能很有用,但触发ViewExpiredException的我的用例不使用返回按钮。第二个参数是什么意思?如果我停留在同一屏幕上,但通过AJAX添加了许多数据,是否需要更多逻辑视图来进行分页?
2个回答

68

首先,Mojarra实现不经意地交换了这些上下文参数的含义。因此,如果您有这样的印象,即描述与字面上的上下文参数名称所暗示的正好相反,那么这确实是真的。


com.sun.faces.numberOfLogicalViews

这基本上是基于GET请求的。每个GET请求都会在会话中创建一个新视图。
要进行实验,请将其设置为3,启动新的浏览器会话并依次打开4个不同的浏览器选项卡(无论URL是否相同),然后返回第1个选项卡并提交其中的表单。您将收到一个ViewExpiredException异常,因为此视图已从会话中的LRU(最近最少使用)映射中推出。如果您最多只打开了3个选项卡,则不会发生这种情况。
默认值为15,这是一个罕见的现实世界问题。如果您的web应用程序真的设计成这样使用(例如社交/社区网站,邀请在多个选项卡中打开,如讨论论坛或问答),则可以考虑使用客户端状态保存而不是增加默认值。使用客户端状态保存,您将永远不会面临此异常。另一种选择是结合请求作用域bean和请求参数或视图作用域bean使用OmniFaces <o:enableRestorableView>,或者在(post)构造中检查自己的状态是否需要恢复。再次提供另一种选择是使用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 postbacks 上看到完全相同的 javax.faces.ViewState 值来确认它)。无论如何,它都不支持浏览器的返回按钮。浏览器的返回按钮只会带您返回到上一个同步请求,因此在会话中存储所有这些 Ajax postbacks 作为逻辑视图是没有意义的。

默认值为15,当前趋势是仅使用ajax表单和在动态页面上禁用缓存,因此这是一个非常罕见的实际问题。正确设计的表单不应该邀请用户按浏览器的返回按钮。相反,成功提交后应重定向到目标视图,失败时只需重新显示带有验证错误的相同表单。请参见如何在JSF中导航?如何使URL反映当前页面(而不是上一页)获取提示。此外,缓存在动态页面上通常被禁用,因此返回按钮基本上会给您带来全新的视图。另请参见避免JSF Web应用程序上的返回按钮。如果这也是您的应用程序情况,则可以安全地将该值设置为1。

MyFaces最初没有相应的功能,也将此视为会话中的物理视图。在2.0.6版本中,引入了org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION,其目的类似,但实现不同,并默认禁用。


参见:


@BalusC:你的意思是JSF Mojarra可以每个逻辑视图存储15个物理视图,每个物理视图包含多个表单。 - Farhan stands with Palestine
@Shirgill:每个物理视图有15个物理视图和15个逻辑视图。这与表单的数量无关(您可以通过查看它们在javax.faces.ViewState隐藏字段中具有相同的值来确认)。 - BalusC
@BalusC:就实际情况而言,就像对于一个像ZEEF这样的网站一样,它的javax.faces.STATE_SAVING_METHOD设置为server,如果我通过打开16个标签来发送16个GET请求,然后转到第一个标签并通过按下命令按钮提交某些内容,如果com.sun.faces.numberOfLogicalViews为15,则会发生viewexpiredexcetion。你选择服务器作为状态保存方面的原因是什么? - Farhan stands with Palestine
@BalusC:这是针对您上面答案的一部分的情境 - 并且提到上面 - 如果您的Web应用程序真的设计成以这种方式使用(例如,社交/社区网站,邀请在多个选项卡中打开,例如讨论论坛或问答),那么您可以考虑使用客户端状态保存。 - Farhan stands with Palestine
@Shirgill:ZEEF有太多的表单,客户端状态保存效率不高。ZEEF使用OmniFaces的<o:enableRestorableView>@ViewScoped(unload-aware)。 - BalusC
有没有办法打印会话中的视图数量,以了解它是否达到了numberOfLogicalViews? - Valsaraj Viswanathan

5

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

这可能会有所帮助:

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接