使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean
Posted
技术标签:
【中文标题】使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean【英文标题】:@ViewScoped bean recreated on every postback request when using JSF 2.2 【发布时间】:2013-12-13 14:36:45 【问题描述】:我遇到了与this post 类似的问题,@BalusC 给出了 3 个解决方案的答案,但是:
我没有使用提到的 EL 表达式 我不想采用第二种解决方案(对我来说它已经够复杂了) 部分状态保存设置为 false。我的代码如下:
index.xhtml
:
<?xml version="1.0" encoding="windows-1256" ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Insert title here</title>
</h:head>
<h:body>
<h:form>
<p:panelMenu id="westMenu">
<p:submenu id="sub1" label="System Monitor">
<p:menuitem id="menu1" value="live monitoring"
action="#menusBean.activateMenu('sub1_menu1')"
update=":centerPane,westMenu"
disabled="#menusBean.active['sub1_menu1']" />
<p:menuitem id="menu2" value="reports"
action="#menusBean.activateMenu('sub1_menu2')"
update=":centerPane,westMenu"
disabled="#menusBean.active['sub1_menu2']" />
</p:submenu>
<p:submenu id="sub2" label="Charging System Nodes" />
<p:submenu id="sub3" label="Additional Nodes" />
</p:panelMenu>
</h:form>
<h:panelGroup id="centerPane">
...
</h:panelGroup>
</h:body>
</html>
MenusBean.java
:
package menus;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.view.ViewScoped;
@ManagedBean
@ViewScoped
public class MenusBean implements Serializable
private static final long serialVersionUID = -7793281454064343472L;
private String mainPage="sub1_menu1";
private Map<String, Boolean> active;
public MenusBean()
System.out.println("MenusBean created");
active = new HashMap<>();
active.put(mainPage, true);
active.put("sub1_menu2", false);
public boolean activateMenu(String page)
active.put(mainPage, false);
active.put(page, true);
mainPage = page;
for (Map.Entry<String, Boolean> e : active.entrySet())
System.out.println(e.getKey()+":"+e.getValue());
return true;
public Map<String, Boolean> getActive()
return active;
执行时,我得到:
MenusBean 创建 MenusBean 创建 MenusBean 创建这是怎么引起的,我该如何解决?
【问题讨论】:
【参考方案1】:这个,
import javax.faces.view.ViewScoped;
是JSF 2.2-introduced CDI-specific 注释,旨在与特定于CDI 的bean 管理注释@Named
结合使用。
但是,您使用的是特定于 JSF 的 bean 管理注释 @ManagedBean
。
import javax.faces.bean.ManagedBean;
然后您应该使用由相同的javax.faces.bean
package 提供的任何范围。右边@ViewScoped
在那边:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class MenusBean implements Serializable
如果您使用了错误的组合,该 bean 将表现为 @RequestScoped
bean,并在每次调用时重新创建。
或者,如果您的环境支持 CDI(GlassFish/JBoss/TomEE with Weld、OpenWebBeans 等),那么您也可以将 @ManagedBean
替换为 @Named
:
import javax.inject.Named;
import javax.faces.view.ViewScoped;
@Named
@ViewScoped
public class MenusBean implements Serializable
建议迁移到 CDI。特定于 JSF 的 bean 管理注释将在未来的 JSF/Java EE 版本中被弃用,因为一切都在缓慢地向 CDI 移动/统一。
【讨论】:
ok awsome,这解决了问题,但只是部分 :( ,在更改注释并加载页面后,它工作正常,但是当我进入“报告”菜单时,它开始再次创建又一次,当我回到“实时监控”菜单时,它会再创建一个并停止。有什么想法吗? 嗯,这很尴尬。 bean 现在是由 JSF 还是 CDI 管理?你试过另一个吗?您是否绝对肯定重建/重新部署成功并且浏览器缓存干净清晰? (在 Chrome 中为 Ctrl+Shift+N)。 老实说,我不知道 CDI 是什么,但我没有 javax.inject 包,所以我想它是由 JSF 管理的(对不起,这里是菜鸟)。 here 是我的项目;我清除了FF中的缓存并尝试使用eclipse内置浏览器,它们都给出了相同的结果。 好的。鉴于您手头没有 CDI,我可以假设您使用 Tomcat 作为服务器吗? 抱歉,无法在 Tomcat 7.0.47 上使用 Mojarra 2.2.4 以及问题中以当前形式发布的确切代码复制它。您是否熟悉基本的 HTTP 以传递请求参数、cookie 等?在 Chrome 中按 F12 并单击 Network 选项卡以查看它。它应该提供有关问题的线索(例如缺少会话 cookie)。以上是关于使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean的主要内容,如果未能解决你的问题,请参考以下文章
为啥 JSF 2.2 需要更多时间在 Wildfly 上部分呈现 ajax 请求
(RC 4.3.4)中的rich:fileUpload 组件在Apache Tomcat7 和JSF 2.2 上工作吗? :“无法读取请求序言”