我的 JSF/RichFaces/Facelets ajax 请求出现了性能问题,据我所知,因为整个组件树都在每个 ajax 请求上重建。即使我使用 ajaxSingle=true,在 a4j:region 中包装部分,声明一个单独的部分用于重新渲染或根本不声明,也会发生这种情况。我们的页面是一个具有许多嵌套级别的动态页面。该页面可能包含大约 800-900 个字段(inputText、丰富的日历、selectOneMenus 等)。初始加载时间是一个问题,但我理解这个问题,它涉及很多领域。一旦我们有了初始构建/渲染时间,尽管我们已经将所有其他操作设计为 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 是否出于某种原因(陈旧的缓存?)确定了此需求。这是我们的堆栈: JBoss 5.1 JSF 1.2 丰富的面孔。 3.3.3. final Facelets 1.1.15 接缝 2.1.2
我尝试添加一些上下文参数以查看它们是否有帮助,但它们什么也没做: facelets.BUILD_BEFORE_RESTORE = 假 facelets.REFRESH_PERIOD = -1 或 5(如 5 分钟)
有没有办法判断我们的 View 是否被正确缓存?我们不关心状态保存方法,所以我相信它默认为服务器端。我们所有的请求都发生在接缝长时间运行的对话中。我不确定这是否是一个因素,因为我认为 View 是在 session 级别缓存的?任何帮助将不胜感激,谢谢。
更多调试后更新:
AjaxViewHandler(它有一个 FaceletsViewHandler 的成员变量)设置了 developmentMode=true。我不确定这是否会导致 facelets 不缓存任何 View ,因此任何更改都会在开发周期中刷新...??很难找到有关 View 的 facelets/JSF 缓存及其行为和控制的任何信息。此外,当我添加配置参数时:
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
这个没带!在调试器中,我仍然看到 true 集。因为我们有很多 subview 我也试过了 com.sun.faces.numberOfLogicalViews 和 com.sun.faces.numberOfViewsInSession 从 15(默认)增加到 1000,这没有任何效果。
我也尝试过更改为客户端状态保存,但没有任何运气。想法用完了……希望有人能帮忙……
似乎 Seam 2.1 会自动初始化 RichFaces,我不确定这是否与它有关......
最佳答案
与任何性能问题一样,分析器将极大地帮助定位瓶颈。 (是的,你知道它是 restore_view 阶段,但不是在 restore_view 阶段的 where)。
也就是说,恢复 View 阶段确实恢复了整个 View ,而不仅仅是将要处理或渲染的部分。引用 RichFaces taglib documentation :
process: Id['s] (in format of call UIComponent.findComponent()) of components, processed at the phases 2-5 in case of AjaxRequest caused by this component. Can be single id, comma-separated list of Id's, or EL Expression with array or Collection
RESTORE_VIEW 是第 1 阶段。另外:
reRender: Id['s] (in format of call UIComponent.findComponent()) of components, rendered in case of AjaxRequest caused by this component. Can be single id, comma-separated list of Id's, or EL Expression with array or Collection
此外,我不确定 UIComponent.findComponent() 是使用比组件树更合适的数据结构实现的。 (在组件树中查找某些东西将归结为线性搜索......)。
我在 JSF 2.0 (Mojarra) 中观察到类似的效果。我的结论是 View 不能包含超过几十个 UIComponents,无论它们是否被渲染。 (换句话说,AJAX 不适合页面导航。)我们打算通过仅包含 View 中当前可见的组件来保持 View 较小,并在需要显示许多新组件时切换 View 。也就是说,我们有 10 个 View ,每个 View 只包含一个选项卡的内容,而不是一个 View 有 10 个选项卡,每个选项卡有 30 个组件。这种方法的一个缺点是组件在切换选项卡时会被释放,导致任何未保存在支持 bean 中的状态都将丢失。
我并不认为这是一个好的解决方案。 las,这是我几周前调查时发现的最好的一个。我也很乐意看到更好的。
编辑
当我说恢复时,我指的是 ViewHandler.restoreView()
,它同时调用初始获取请求和回发。说 restoreView
只是按原样重用现有 View 是不正确的。例如,JSF 2.0 规范在第 7.6.2.7 节中要求:]
The
restoreView()
method must fulfill the following responsibilities:All implementations must:
- If no viewId could be identified, return
null
.- Call the
restoreView()
method of the associatedStateManager
, passing theFacesContext
instance for the current request and the calculated viewId, and return the returnedUIViewRoot
, which may benull
.
在第 7.7.2 节中:
JSF implementations support two primary mechanisms for saving state, based on the value of the javax.faces.STATE_SAVING_METHOD initialization parameter (see Section 11.1.3 “Application Configuration Parameters”). The possible values for this parameter give a general indication of the approach to be used, while allowing JSF implementations to innovate on the technical details:
- client -- [...]
- server -- Cause the saved state to be stored on the server in between requests. Implementations that wish to enable their saved state to fail over to a different container instance must keep this in mind when implementing their server side state saving strategy. The default implementation Serializes the view in both the client and server modes. In the server mode, this serialized view is stored in the session and a unique key to retrieve the view is sent down to the client. By storing the serialized view in the session, failover may happen using the usual mechanisms provided by the container.
换句话说,添加到 JSF 中的 AJAX 支持(RichFaces 3 添加到 JSF 1.2 中的一种,以及合并到 JSF 2.0 中的一种)旨在减少网络带宽消耗,而不是服务器端 cpu 消耗。
关于java - JSF View 在每个 ajax 请求上得到重建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7190225/