Я прочитал отличный ответ, когда разорванный вид бобов уничтожен. (см. How and when is a @ViewScoped bean destroyed in JSF?), и я автоматически предположил, что уничтоженный компонент также удален из кеша области видимости. Но я мог видеть, что bean все еще находится в кеше, поэтому я хотел бы знать, должен ли быть удален удаленный bebe-объект из области просмотра LRU, если когда-либо?Как и когда элемент видимости вида удален из кеша LRU в JSF?
В нашем приложении мы открываем все детали в вкладках/окнах sepeare. После некоторого открытия/закрытия (зависит от numberOfViewsInSession) мы могли бы увидеть ViewExpiredException в том случае, когда первое подробное окно все еще открыто, и пользователь открывает и закрывает другие окна подробностей, и через некоторое время он хочет выполнить некоторую операцию в первом окне. Я сделал некоторую отладку, и я вижу, что закрытое представление не было удалено из кэша LRU.
Так ожидаемое поведение или что-то не так в моем коде? И если это ожидаемое поведение, есть ли какая-нибудь полезная стратегия, как работать с multitabs/multiwindow без большого количества ViewExpiredException, вызванного кешем LRU ?. Я знаю, что могу изменить numberOfViewsInSession, но это последний выбор, который я хочу использовать.
Я подготовил простую тестовую папку, и когда я открываю/закрываю view.xhtml больше раз, я вижу, что LRUMap растет.
Окружающая среда: JDK7, mojarra 2.2.4, 7.0.47 кот
Заранее спасибо
View.xhtml
<!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>
index.xhtml
<!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>
ClosePage.xhmtl
<!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>
ViewBean.java
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);
}
}
SessionBean.java
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";
}
}