JSF 2.1查看每次刷新时重新创建的作用域托管bean

所以我有一个问题,我需要任何有关如何解决这个问题的信息。 我们在JBoss 7.1上使用JSF 2.1,我们正在使用具有与该视图相关的表的视图范围bean。 在该表中表示为行的对象非常大。

在每次刷新这些视图时,都会创建该bean的新实例。

为了validation这是否发生,我创建了一个演示示例:

        

然后将此模板链接到如下定义的bean:

 @ManagedBean @ViewScoped public class ViewScopedBean { private int i = 0; @PostConstruct public void init(){ System.out.println("Init - " + i); } @PreDestroy public void dest(){ System.out.println("Destroy - " + i); } public int getI() { return i; } public void setI(int i) { this.i = i; } } 

每次我使用浏览器刷新按钮刷新视图或只需在浏览器地址字段中按Enter键,我就会清楚地看到@PostConstruct方法调用。

如果我让应用程序保持活动很长时间,我看不到调用@PreDestroy方法,并且进行堆转储显示ViewScopedBean具有与我重新加载视图的数量相同的实例数,并且看起来保持在堆即使我破坏了会话。

这对我来说是一个很大的问题,因为如果有500个用户使用那个大表重新加载视图,JBoss会因为它的堆空间已满而死掉。

这是@ViewScoped bean的设计行为还是我做错了什么?

只要用户通过将回发返回到同一视图(通过从UICommand操作方法返回null / void )与当前视图交互,就可以查看作用域bean。 从操作方法返回当前视图ID,将get请求发送到同一视图,刷新页面,在浏览器的地址栏中手动输入URL以及这些事件都会导致重新创建视图。 因此,您会看到在每个此类操作上重新实例化视图范围bean。

每次创建视图时都会创建ViewScoped bean。 就是这样。

但是你抱怨如果有500个用户来到这个页面,JBoss就会死掉。 可用于防止这种情况的唯一范围是ApplicationScope 。 但这是一个坏主意。

每个人都会建议你使用最窄的范围。 所以我认为你的问题的解决方案不是另一个范围,而是一个“延迟加载”算法。 您应该逐页加载表。 我不认为每个人都会在一次阅读中需要整个表格。

这是对范围的一个很好的描述。 ManagedBeanScopes

如果你想要销毁bean,你应该选择requestScope。 因为viewcoped bean存储在会话中。