【发布时间】:2016-12-25 02:28:21
【问题描述】:
我们在启用 JSF 2.2 + PrimeFaces 的应用程序中使用 SPA 方法。 最初在这里很好地描述了基本思想:
Refreshing dynamic content with AJAX in JSF using SPA approach
但是,正如我们所知,在使用 @ViewScoped bean 时,使用这种 SPA 方法有一个缺点。
由于我们实际上总是停留在同一个 JSF 视图中,所以当我们用新的 SPA 内容替换面板组的内容时,@ViewScoped bean 不会从内存中删除。
我找到了解决方案,但我想知道它是否是正确的方法,和/或是否缺少任何东西。
基本上,在我们的 NavigationService bean 中,它包含在 SPA AJAX 请求期间要呈现的页面的名称,我们总是执行以下代码:
private void clearViewScopedBeans() {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> entry = it.next();
it.remove();
}
}
这应确保在呈现新的 SPA sn-p 后,删除所有先前存在的 @ViewScoped bean。
但是,我认为上面的代码只删除了 View Scoped bean,而不是相关的 View States。对吗?
我发现了一个旧的博客条目,它似乎做了更多的逻辑: http://javaevangelist.blogspot.sg/2014/08/jsf-21-tip-of-day-clearing-viewscope.html
但我也不知道它是否正确。
另外,如果我们想支持多窗口标签,我们的NavigationService bean,持有当前SPA sn-p页面名称,也必须是@ViewScoped,这引入了一个小问题:
在运行上述代码以删除所有现有的@ViewScoped bean 时...我们必须排除 NavigationService bean 本身!否则我们最终总是加载相同的页面,因为 NavigationService 的一个新实例被实例化,使用默认的 SPA 页面名称,而不是新的。
所以,总而言之,我们的代码最终看起来像这样,其中我们保留了一个“排除”bean 名称的 Map,我们不想在 SPA 页面刷新时删除它(即包含 SPA 页面的 NavigationService bean名字)
private void clearViewScopedBeans() {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext(); ) {
Map.Entry<String, Object> entry = it.next();
if(!exclusionViewScopedBeans.contains(entry.getKey())) {
logger.info("Removing an instance of a @ViewScoped bean -> " + entry.getKey());
it.remove();
}
}
}
现在的问题是……这是处理这类 SPA 情况的正确方法吗?我们在这里遗漏了什么吗?
任何反馈都将不胜感激......提前非常感谢!
【问题讨论】:
-
这就是我使用的实现——就正确的方法而言,我得到的印象是你应该在 JSF 中避免这种事情,但现实是有时你需要这样做
-
为什么不使用对话范围的 bean?
-
因为这个特定的项目使用 Spring IoC 而不是 CDI...所以到目前为止还没有内置的 Conversation 范围。 :( 无论如何,我也在考虑创建可以实现相同功能的新(Spring)范围。到目前为止,我已经成功地为 PrimeFaces TabView 组件创建了一个 TabScope。每个选项卡都可以有自己的 JSF bean 范围,在构建选项卡时创建,并在关闭选项卡时销毁。我想我可以使用相同的方法来开发更通用的对话范围 ...
标签: jsf primefaces cdi single-page-application view-scope