Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何以及何时从JSF中的LRU缓存中删除视图范围bean?_Jsf_Jsf 2_View Scope - Fatal编程技术网

如何以及何时从JSF中的LRU缓存中删除视图范围bean?

如何以及何时从JSF中的LRU缓存中删除视图范围bean?,jsf,jsf-2,view-scope,Jsf,Jsf 2,View Scope,当视图范围的bean被销毁时,我读到了一个极好的答案。(请参阅)并且我自动假设已销毁的bean也从视图范围缓存中删除。但是我可以看到bean仍然在缓存中,所以我想知道是否应该从LRU视图范围缓存中删除销毁的视图范围bean,如果有的话 在我们的应用程序中,我们在单独的选项卡/窗口中打开所有详细信息。在一些打开/关闭(取决于numberOfViewsInSession)之后,我们可以看到ViewExpiredException,以防第一个详细信息窗口仍然打开,并且用户一直在打开和关闭另一个详细信息

当视图范围的bean被销毁时,我读到了一个极好的答案。(请参阅)并且我自动假设已销毁的bean也从视图范围缓存中删除。但是我可以看到bean仍然在缓存中,所以我想知道是否应该从LRU视图范围缓存中删除销毁的视图范围bean,如果有的话

在我们的应用程序中,我们在单独的选项卡/窗口中打开所有详细信息。在一些打开/关闭(取决于numberOfViewsInSession)之后,我们可以看到ViewExpiredException,以防第一个详细信息窗口仍然打开,并且用户一直在打开和关闭另一个详细信息窗口,并且在一段时间后他想在第一个窗口中执行某些操作。我已经做了一些调试,我可以看到关闭的视图没有从LRU缓存中删除

那么,这是预期的行为还是我的代码中有错误?如果这是预期的行为,那么有没有什么有用的策略来处理multitabs/multiwindow,而不必使用LRU缓存导致的大量ViewExpiredException?。我知道我可以在会话中更改NumberOfViews,但这是我想使用的最后一个选项

我准备了一个简单的测试用例,当我打开/关闭view.xhtml更多次时,我可以看到LRUMap正在增长

环境:JDK7、mojarra 2.2.4、tomcat 7.0.47

提前谢谢

view.xhtml


我认为每个JSF开发人员最终都会遇到这种情况。真正的问题在于,您无法设计出一个真正可靠的有状态系统,在该系统中,浏览器将向ViewScope bean发出信号,表明已完成了对页面的处理,从而允许支持bean自行销毁。这就是为什么JSF实现有LRU缓存来限制会话所使用的内存,这对于日常应用来说是一个很好的全面解决方案

在一些情况下,您知道已经完成了ViewScoped bean,例如来自该bean的重定向。对于这些,您可以编写自己的视图处理程序来执行更智能的缓存系统,但这不是一项简单的任务,坦率地说,不值得这么做

我提出的最简单的解决方案是使用一个javascript计时器在每个页面上使用一个ViewScoped bean执行一个ajax回发到服务器。(将此计时器设置为每30秒执行一次似乎是合理的。)这将把与页面关联的ViewScope bean移动到LRU缓存的底部,确保它们不会过期

特别是,我使用primefaces轮询组件来实现这一点,并将其粘贴到所有ViewScope bean使用的模板中。通过将此组件以其自身的形式放置,请求大小保持较小

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html">
    <head>
        <title>View Bean</title>
        <meta charset="UTF-8"/>
    </head>
    <body>
        <h:form id="viewForm">
        <div>#{viewBean.text}</div>
        <h:commandButton id="closeButton" value="Close" action="/ClosePage.xhtml"/>
        </h:form>
    </body>
</html>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Session bean</title>
    </h:head>
    <h:body>
        <h:form id="sessionForm">
            <h:outputText value="#{sessionBean.text}"/>
            <br/>
            <h:link id="linkView" value="Open view.xhmtl" outcome="/view.xhtml" target="_blank"/>
        </h:form>
    </h:body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">               
    <head><title>Window will be closed</title></head>
    <body>
        <script>window.close();</script>
    </body>
</html>
package com.mycompany.mavenproject2;

import com.sun.faces.util.LRUMap;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

@ManagedBean(name = "viewBean")
@ViewScoped
public class ViewBean implements Serializable {

    private static final long serialVersionUID = 13920902390329L;

    private int lruMapSize;

    /**
     * Creates a new instance of ViewBean
     */
    public ViewBean() {

        Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
        LRUMap<String, LRUMap> lruMap = (LRUMap) sessionMap.get("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap");
        lruMapSize = lruMap == null ? 0 : lruMap.size();
    }

    @PreDestroy
    void destroyed() {
        System.out.println("View bean destroyed");
    }

    public String getText() {
        return "ViewBean LRU cache size:" + Integer.toString(lruMapSize);
    }

} 
package com.mycompany.mavenproject2;

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name = "sessionBean")
@SessionScoped
public class SessionBean implements Serializable {
    private static final long serialVersionUID = 1777489347L;

    /**
     * Creates a new instance of SessionBean
     */
    public SessionBean() {
    }

    public String getText() {
        return "Session bean text";
    }

}