如何处理@ViewScoped 页面中的'cached' 实例?
How to deal with 'cached' instance in @ViewScoped page?
App 运行 JSF
, Primefaces
, eclipselink
, 不是一个小应用程序,大约 100 个 pages/bean 都能完美运行
我在理解 @ViewScoped
页面的工作原理时遇到了一些麻烦,我得到了一个 select
UI 组件,其中包含一个简单的 List<People>
和一个后端 selectedPeople
在我的豆子里
// all getters, setters, JPA annotations, all good
public class People {
private String name;
private List<Car> cars;
}
@ManagedBean
@ViewScoped
public class PeopleBean {
@EJB
private Service sPeople;
private People selectedPeople;
private List<People> listPpl;
@PostConstruct
public void init(){
listPpl = sPeople.readAll(); // always good, same as DB values
}
public People getSelectedPeople(){
return selectedPeople;
}
public People setSelectedPeople(People p){ // p is an old element
selectedPeople = p; // BREAKPOINT
}
// getter for the list too
public void method(){
Logger.getAnoymousLogger().severe(selectedPeople.getCars()); // the one the old people, not the ne contained in the actual list
}
}
<p:selectOneMenu id="selectP" value="#{peopleBean.selectedPeople}" converted="#{genericSecuerdConverter}" >
<p:ajax event="change" partialSubmit="true" listener="#{peopleBean.method()}" />
<f:selectItems value="#{peopleBean.listPpl}" var="people" itemLabel="#{people.name}" itemValue="#{people}" />
</p:selectOneMenu>
使用顺序和问题是(从调试中获取的信息):
- 转到
peoplePage.xhtml
,其中 select 元素所在,列表元素的 IDs
是 #410, #411, #412
(3 人)
- 去
modif.xhtml
,换第3个人(去掉一个car
,保存在DB里(check in DB))
- 回到
peoplePage.xhtml
,列表正常,调试中的IDs
是#650, #651, #652
- 改变selectUI的值(来自
null
)选择一个人,在断点处,p
看起来是 #412
元素,所以它的 car's list 上的变化是不可见的,它不是来自 listPpl
(因为只包含有效元素并且对应 DB),它很好缓存
我试图禁用 ecpliselink 缓存作为状态 EclipleLink cache
- 更改 eclipselink 属性
- 更改 JPA 属性
- 使用
@Cacheable(false)
没有任何影响,也没有进入私人导航,也没有清除浏览器缓存并返回页面,p
元素仍然是第一次加载时的旧元素
我以为@ViewScoped
允许每次像第一次一样打开一个页面,但似乎不是,无法确定元素可以在哪里stored/cached
编辑 目前我使用了一个解决方法,但这显然是最好的解决方案
public People setSelectedPeople(People p){
if(p!=null)
selectedPeople = sPeople.read(p.getId());
}
您要找的是@RequestScoped
。每次您执行合适的 HTTP 请求时,它都会创建所有内容。否则不能保证销毁 @ViewScoped
bean。 Omnifaces 文档中的示例:ViewScoped.
例如,当用户使用浏览器的后退和前进按钮时,此功能可用于帮助重新创建页面。
@RequestScoped
Bean lives as long as the HTTP request-response lives. It gets created upon a HTTP request and gets destroyed when the HTTP response associated with the HTTP request is finished.
@ViewScoped
Bean lives as long as the user is interacting with the same JSF view in the browser window/tab. It gets created upon a HTTP request and gets destroyed once the user postbacks to a different view.
描述来源:https://www.tutorialspoint.com/jsf/jsf_managed_beans.htm
App 运行 JSF
, Primefaces
, eclipselink
, 不是一个小应用程序,大约 100 个 pages/bean 都能完美运行
我在理解 @ViewScoped
页面的工作原理时遇到了一些麻烦,我得到了一个 select
UI 组件,其中包含一个简单的 List<People>
和一个后端 selectedPeople
在我的豆子里
// all getters, setters, JPA annotations, all good
public class People {
private String name;
private List<Car> cars;
}
@ManagedBean
@ViewScoped
public class PeopleBean {
@EJB
private Service sPeople;
private People selectedPeople;
private List<People> listPpl;
@PostConstruct
public void init(){
listPpl = sPeople.readAll(); // always good, same as DB values
}
public People getSelectedPeople(){
return selectedPeople;
}
public People setSelectedPeople(People p){ // p is an old element
selectedPeople = p; // BREAKPOINT
}
// getter for the list too
public void method(){
Logger.getAnoymousLogger().severe(selectedPeople.getCars()); // the one the old people, not the ne contained in the actual list
}
}
<p:selectOneMenu id="selectP" value="#{peopleBean.selectedPeople}" converted="#{genericSecuerdConverter}" >
<p:ajax event="change" partialSubmit="true" listener="#{peopleBean.method()}" />
<f:selectItems value="#{peopleBean.listPpl}" var="people" itemLabel="#{people.name}" itemValue="#{people}" />
</p:selectOneMenu>
使用顺序和问题是(从调试中获取的信息):
- 转到
peoplePage.xhtml
,其中 select 元素所在,列表元素的IDs
是#410, #411, #412
(3 人) - 去
modif.xhtml
,换第3个人(去掉一个car
,保存在DB里(check in DB)) - 回到
peoplePage.xhtml
,列表正常,调试中的IDs
是#650, #651, #652
- 改变selectUI的值(来自
null
)选择一个人,在断点处,p
看起来是#412
元素,所以它的 car's list 上的变化是不可见的,它不是来自listPpl
(因为只包含有效元素并且对应 DB),它很好缓存
我试图禁用 ecpliselink 缓存作为状态 EclipleLink cache
- 更改 eclipselink 属性
- 更改 JPA 属性
- 使用
@Cacheable(false)
没有任何影响,也没有进入私人导航,也没有清除浏览器缓存并返回页面,p
元素仍然是第一次加载时的旧元素
我以为@ViewScoped
允许每次像第一次一样打开一个页面,但似乎不是,无法确定元素可以在哪里stored/cached
编辑 目前我使用了一个解决方法,但这显然是最好的解决方案
public People setSelectedPeople(People p){
if(p!=null)
selectedPeople = sPeople.read(p.getId());
}
您要找的是@RequestScoped
。每次您执行合适的 HTTP 请求时,它都会创建所有内容。否则不能保证销毁 @ViewScoped
bean。 Omnifaces 文档中的示例:ViewScoped.
例如,当用户使用浏览器的后退和前进按钮时,此功能可用于帮助重新创建页面。
@RequestScoped Bean lives as long as the HTTP request-response lives. It gets created upon a HTTP request and gets destroyed when the HTTP response associated with the HTTP request is finished.
@ViewScoped Bean lives as long as the user is interacting with the same JSF view in the browser window/tab. It gets created upon a HTTP request and gets destroyed once the user postbacks to a different view.
描述来源:https://www.tutorialspoint.com/jsf/jsf_managed_beans.htm