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

时间:2013-10-03 07:32:49

标签: java jsf jsf-2

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

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

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

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
        <h:outputText value="#{viewScopedBean.i}" />
</h:body>
</html> 

然后将此模板链接到如下定义的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的设计行为还是我做错了什么?

2 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:0)

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

但是你抱怨如果有500个用户来到这个页面JBoss会死掉。您可以使用的唯一范围是ApplicationScope。但这是一个坏主意。

每个人都会建议你使用最窄的范围。 所以我认为你的问题的解决方案不是另一个范围,而是一个&#34;懒惰的负载&#34;算法。您应该逐页加载表。我不认为每个人都需要一次阅读全桌。

以下是范围的良好描述。 ManagedBeanScopes

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