Java JSF视图在每个ajax请求上获得重建

Java JSF视图在每个ajax请求上获得重建,java,jsf,richfaces,facelets,Java,Jsf,Richfaces,Facelets,我的JSF/RichFaces/Facelets ajax请求有一个性能问题,从我可以看出,这是因为每个ajax请求都在重建整个组件树。即使我使用ajaxSingle=true,在a4j:region中包装节,声明单个节用于重新排序,或者根本不使用,也会发生这种情况。我们的页面是一个具有许多嵌套级别的动态页面。该页面可能包含大约800-900个字段(inputText、rich calendars、SelectOne菜单等)。初始加载时间是一个问题,但我理解这个问题,它有很多字段。一旦我们有了最

我的JSF/RichFaces/Facelets ajax请求有一个性能问题,从我可以看出,这是因为每个ajax请求都在重建整个组件树。即使我使用ajaxSingle=true,在a4j:region中包装节,声明单个节用于重新排序,或者根本不使用,也会发生这种情况。我们的页面是一个具有许多嵌套级别的动态页面。该页面可能包含大约800-900个字段(inputText、rich calendars、SelectOne菜单等)。初始加载时间是一个问题,但我理解这个问题,它有很多字段。一旦我们有了最初的构建/呈现时间,尽管我们已经将所有其他操作设计为ajax,并且只重新呈现所需的内容。从facelets调试日志中,我可以在任何ajax调用中看到如下消息:

2011-08-24 22:19:03,054 DEBUG [facelets.viewhandler] (http-0.0.0.0-8080-2) Took
24445ms to build view: /oconsole/appfile.xhtml
2011-08-24 22:19:09,377 DEBUG [facelets.viewhandler] (http-0.0.0.0-8080-2) Took
6323ms to render view: /oconsole/appfile.xhtml
我不确定我们正在做的事情是否导致了整个组件树的重建,或者facelets出于某种原因(过时的缓存?)。这是我们的堆栈: JBoss5.1 JSF1.2 富有的面孔。3.3.3.最终版本 Facelets 1.1.15 接缝2.1.2

我尝试添加一些上下文参数以查看它们是否有帮助,但它们没有起到任何作用: facelets.BUILD\u BEFORE\u RESTORE=false facelets.REFRESH_PERIOD=-1或5(如5分钟)

是否有任何方法可以判断我们的视图是否被正确缓存?我们不关心状态保存方法,所以我相信它默认为服务器端。我们的所有请求都发生在seam长时间运行的对话中。我不确定这是否是一个因素,因为我认为在会话级别缓存视图?任何帮助都将不胜感激,谢谢

进行更多调试后更新:

AjaxViewHandler(具有FaceletsViewHandler的成员变量)设置了developmentMode=true。我不确定这是否会导致facelets不缓存任何视图,以便在开发周期中刷新任何更改。。。??很难找到任何关于facelets/JSF缓存视图及其行为和控制的信息。此外,当我添加配置参数时:

<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>

facelets.DEVELOPMENT
假的
这可没用!在调试器中,我仍然看到true set。因为我们有很多子视图,所以我也尝试了 com.sun.faces.numberofLogicalView和 com.sun.faces.numberofviewsin会话 从15(默认值)增加到1000,这没有效果

我还尝试了在没有任何运气的情况下切换到客户端状态保存。没有主意了…希望有人能帮忙


Seam 2.1似乎自动初始化了RichFaces,我不确定这是否与此有关……

与任何性能问题一样,探查器将大大有助于找到瓶颈。(是的,您知道这是还原视图阶段,但不是还原视图阶段中的位置)

也就是说,“恢复视图”阶段确实恢复了整个视图,而不仅仅是将要处理或渲染的部分。引述:

进程:组件的Id['s](以调用UIComponent.findComponent()的格式),如果此组件导致AjaxRequest,则在第2-5阶段进行处理。可以是单个id、以逗号分隔的id列表,也可以是带有数组或集合的EL表达式

恢复视图是第1阶段。此外:

reRender:Id['s](以调用UIComponent.findComponent()的格式),在该组件导致AjaxRequest的情况下呈现。可以是单个id、以逗号分隔的id列表,也可以是带有数组或集合的EL表达式

此外,我不确定UIComponent.findComponent()是否使用比组件树更合适的数据结构实现。(在组件树中查找内容可以归结为线性搜索…)

我在JSF2.0(Mojarra)中观察到了类似的效果。我的结论是,视图不能包含超过几十个UIComponent,无论它们是否呈现。(换句话说,AJAX不适合页面导航。)我们决定只包含视图中当前可见的组件,并在需要显示许多新组件时切换视图,从而保持视图的小型化。也就是说,我们将有10个视图,每个视图包含10个选项卡,每个选项卡包含30个组件,而不是一个视图,每个视图只包含单个选项卡的内容。这种方法的一个缺点是,在切换选项卡时会处理组件,导致任何未保存在备份bean中的状态丢失

我并不认为这是一个好的解决办法。唉,这是我在几周前调查这件事时发现的最好的一件。我也很高兴看到一个更好的

编辑 当我说restore时,我指的是
ViewHandler.restoreView()
,它同时调用初始get请求和回发。如果说
restoreView
只会按原样重用现有视图,这是不正确的。例如,JSF2.0规范在第7.6.2.7节中规定:]

restoreView()
方法必须履行以下职责:

所有实施必须:

  • 如果无法识别viewId,则返回
    null
  • 调用关联的
    StateManager
    restoreView()
    方法,将
    FacesContext
    实例传递给 当前请求和计算的viewId,并返回返回的
    UIViewRoot
    ,它可能是
    null
第7.7.2节:

JSF实现基于 javax.faces.STATE_SAVING_方法初始化参数(参见第11.1.3节“应用程序配置 参数”)。该参数的可能值给出了拟使用方法的一般指示,同时允许 JSF实现在技术细节上进行创新:

  • 客户--[…]
  • 服务器--使保存的状态在请求之间存储在服务器上。希望启用的实现 必须记住,它们的保存状态将故障转移到不同的容器实例
            // build view - but not if we're in "buildBeforeRestore"
            // land and we've already got a populated view. Note
            // that this optimizations breaks if there's a "c:if" in
            // the page that toggles as a result of request processing -
            // should that be handled? Or
            // is this optimization simply so minor that it should just
            // be trimmed altogether?
            if (!this.buildBeforeRestore
                    || viewToRender.getChildren().isEmpty()) {
                this.buildView(context, viewToRender);
            }