com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews

时间:2010-11-05 11:28:23

标签: jsf jsf-2 viewstate mojarra viewexpiredexception

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

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

他们之间有什么区别?文档中没有提到这些内容。我的应用程序在某些页面上遇到ViewExpiredException问题,但在我们将这些设置提高到(更高)值后,我们就停止了问题。

我的应用程序是一个财务,重量级,支持Ajax的应用程序(有些屏幕有50多个输入,可以选择通过AJAX添加更多数据/输入)。

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

2 个答案:

答案 0 :(得分:63)

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


com.sun.faces.numberOfLogicalViews

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

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

默认值为15,这是一个罕见的现实世界问题。如果您的webapp真的被设计为以这种方式使用(例如,邀请在多个选项卡中打开的社交/社区站点,例如讨论论坛或Q&amp; A),那么您可以考虑使用客户端状态保存而不是增加默认值。通过客户端状态保存,您将永远不会遇到此异常。另一种方法是将OmniFaces <o:enableRestorableView>组合使用请求范围的bean和请求参数,或者使用视图范围bean检查(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回发上返回的完全相同的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,但具有相似的目的,但具有不同的实现,默认情况下已禁用。


另见:

答案 1 :(得分:5)

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

这可能会有所帮助:

  

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