使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean [英] @ViewScoped bean recreated on every postback request when using JSF 2.2

查看:19
本文介绍了使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了类似于 这篇文章和@BalusC的回答,有3个解决方案,但是:

  • 我没有使用提到的 EL 表达式
  • 我不想采用第二种解决方案(它对我来说已经足够复杂了)
  • 并且部分状态保存设置为 false.

我的代码如下:

index.xhtml:

<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:头><title>在此处插入标题</title></h:head><h:body><h:形式><p:panelMenu id="westMenu"><p:submenu id="sub1" label="系统监视器"><p:menuitem id="menu1" value="实时监控"action="#{menusBean.activateMenu('sub1_menu1')}"更新=":centerPane,westMenu"disabled="#{menusBean.active['sub1_menu1']}"/><p:menuitem id="menu2" value="reports"action="#{menusBean.activateMenu('sub1_menu2')}"更新=":centerPane,westMenu"disabled="#{menusBean.active['sub1_menu2']}"/></p:子菜单><p:submenu id="sub2" label="充电系统节点"/><p:submenu id="sub3" label="其他节点"/></p:panelMenu></h:form><h:panelGroup id="centerPane">...</h:panelGroup></h:body>

MenusBean.java:

包菜单;导入 java.io.Serializable;导入 java.util.HashMap;导入 java.util.Map;导入 javax.faces.bean.ManagedBean;导入 javax.faces.bean.SessionScoped;导入 javax.faces.view.ViewScoped;@ManagedBean@ViewScoped公共类 MenusBean 实现了可序列化{private static final long serialVersionUID = -7793281454064343472L;private String mainPage="sub1_menu1";私有映射<字符串,布尔值>积极的;公共菜单豆(){System.out.println("MenusBean 已创建");active = new HashMap<>();active.put(mainPage, true);active.put("sub1_menu2", false);}公共布尔激活菜单(字符串页面){active.put(mainPage, false);active.put(page, true);mainPage = 页面;for (Map.Entry e : active.entrySet())System.out.println(e.getKey()+":"+e.getValue());返回真;}公共地图<字符串,布尔值>获取活动(){返回活跃;}}

执行时,我得到:

<前>创建的 MenusBean创建的 MenusBean创建的 MenusBean

这是怎么引起的,我该如何解决?

解决方案

这个,

import javax.faces.view.ViewScoped;

JSF 2.2 引入的 CDI 特定 注释,旨在与特定于 CDI 的 bean 管理注释 @Named 结合使用.

但是,您正在使用 JSF 特定的 bean 管理注释 @ManagedBean.

import javax.faces.bean.ManagedBean;

然后您应该使用由相同的 javax.faces.bean.正确的@ViewScoped 在那边:

import javax.faces.bean.ManagedBean;导入 javax.faces.bean.ViewScoped;@ManagedBean@ViewScoped公共类 MenusBean 实现了可序列化{

如果您使用错误的组合,该 bean 将表现为 @RequestScoped bean 并在每次调用时重新创建.

或者,如果您的环境支持 CDI(GlassFish/JBoss/TomEE with Weld、OpenWebBeans 等),那么您也可以将 @ManagedBean 替换为 @Named:

import javax.inject.Named;导入 javax.faces.view.ViewScoped;@命名@ViewScoped公共类 MenusBean 实现了可序列化{

建议转移到 CDI.特定于 JSF 的 bean 管理注释在未来的 JSF/Java EE 版本中可能会被弃用,因为一切都在慢慢地朝着 CDI 移动/统一.

I'm having an issue similar to this post and the answer from @BalusC with 3 solutions but:

  • I'm not using of the mentioned EL expressions
  • I don't want to go with the second solution (it's complex enough for me like this)
  • and partial state saving is set to false.

My code is as follows:

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;
    }
}

When executed, I get:

MenusBean created
MenusBean created
MenusBean created

How is this caused and how can I solve it?

解决方案

This,

import javax.faces.view.ViewScoped;

is the JSF 2.2-introduced CDI-specific annotation, intented to be used in combination with CDI-specific bean management annotation @Named.

However, you're using the JSF-specific bean management annotation @ManagedBean.

import javax.faces.bean.ManagedBean;

You should then be using any of the scopes provided by the very same javax.faces.bean package instead. The right @ViewScoped is over there:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class MenusBean implements Serializable{

If you use the wrong combination, the bean behaves as a @RequestScoped bean and be recreated on each call.

Alternatively, if your environment supports CDI (GlassFish/JBoss/TomEE with Weld, OpenWebBeans, etc), then you could also replace @ManagedBean by @Named:

import javax.inject.Named;
import javax.faces.view.ViewScoped;

@Named
@ViewScoped
public class MenusBean implements Serializable{

It's recommended to move to CDI. The JSF-specific bean management annotations are candidate for deprecation in future JSF / Java EE versions as everything is slowly moving/unifying towards CDI.

这篇关于使用 JSF 2.2 时在每个回发请求上重新创建 @ViewScoped bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆