【问题标题】:ViewScope constructor called twice, not sure whyViewScope 构造函数调用了两次,不知道为什么
【发布时间】:2011-06-21 12:50:25
【问题描述】:

我已经看到有关调用 bean 构造函数和 ViewScope 的其他问题,但我仍然遇到困难。我看到的问题涉及我的应用程序中的两个特定页面。第一个是一个数据表(现在它填充了随机生成的数据,但最终会调用一个数据库),第二个页面是一个相当简单的显示页面,其中来自所选行的信息以表格形式显示以供编辑或查看 -这是我的detail.xhtml 页面。这个页面的 bean 才是问题所在;它的构造函数被调用了两次:第一次当我导航到页面时,再次按下commandButton 提交更改或取消更改无关紧要,第二次调用detail.xhtml 支持bean 的构造函数。

我的 bean 是 @ViewScoped,正在导入 javax.faces.bean.ViewScoped。其他一些可能会产生影响的细节,但如果他们这样做,我不明白为什么:我的 UserDetailBean.java 继承自一个基本 bean(我最初称之为 UIBaseBean.java)。现在,我的 UIBaseBean 是@RequestScoped。据我了解,这应该没什么区别,因为我的 UserDetailBean 是@ViewScoped,如果我错了,请纠正我。

另一个可能产生影响的细节是 UIBaseBean 和 UserDetailBean 的构造函数中的变量设置。我想在页面顶部的工具栏中显示用户的位置。为此,我在 UIBaseBean 中创建了一个变量:

protected String toolbarDescription;

我还在 UIBaseBean 中提供了 setter 和 getter。在 UIBaseBean 的构造函数中,我定义了变量:

toolbarDescription = "fix me";

该定义只是为了让我知道为我的应用程序中的任何特定页面覆盖支持 bean 中的变量。在我的 UserDetailBean 中,我为字符串工具栏描述分配了一个新值。此值显示在 detail.xhtml 页面上。否则,我的 detail.xhtml 页面的 bean 非常简单,它获取和设置用于在 detail.xhtml 页面上的表单中显示数据的属性。

已设置详细信息页面,因此导航到它时会发生重定向,而导航离开(当按下 commandButton 时)会发生重定向。我尝试过使用有和没有重定向的 faces-config 导航规则,以及有和没有重定向的隐式导航,但是 UserDetailBean 构造函数总是被调用两次。

哦,我在 UserDetailBean 构造函数中的 toolbarDescription 变量上设置了一个断点,这会停止程序两次:第一次调用页面时,以及在详细页面上按下 commandButton 后再次停止。

根据我的描述,谁能告诉我为什么我的构造函数被调用了两次?是我错误地设计了我的 bean,还是我的应用程序中的问题更深层次?

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import [package name].UIBaseBean;    
import java.util.Locale;
import javax.faces.bean.ManagedProperty;


@ManagedBean
@ViewScoped

public class UserDetailBean extends UIBaseBean {

@ManagedProperty(value = "#{param.action}")
private String action;

private String firstName;
private String lastName;
private String jobTitle;
private String DOH;
private String location;
private String status;
private String comments;
@ManagedProperty(value = "#{param.id}")
private String id;
private String tabTitle;

private boolean editMode;
private boolean viewMode;

private ClUserDetail dBUserDetail;      

    /** Creates a new instance of UserDetailBean */
    public UserDetailBean() {   
        toolbarDescription = CoreMsgBundle.getMessageFromResourceBundle("UserDetail", Locale.ENGLISH);
    }

【问题讨论】:

    标签: java jsf-2 backing-beans


    【解决方案1】:

    您需要从UIBaseBean 中删除@RequestScoped 和其他相关注释(并使其变为abstract)。

    完成后,您还需要将#{param} 上的@ManagedProperty 修复为由<f:viewParam> 定义或由ExternalContext#getRequestParameterMap() 获取。即不可能将具有更短范围的东西注入具有更大范围的东西(因为不清楚应该注入哪个,因为在接受器的范围内可能会有更多)。 JSF 会在 bean 的构建过程中抛出异常。

    【讨论】:

    • 非常感谢,这完全符合我希望原始代码能够正常工作的效果。至于@ManagedProperty - 这是一个小信息的例子,没有很好的理解是一件坏事。我阅读了this answer 并想,“哦,好主意,我会在我的应用程序中这样做”。
    • @balusc 我有一个类似的问题,我的 ViewScoped bean 构造函数被多次调用。 bean 确实扩展了一个提供实用功能但不是 bean 本身的基类。根据您在此处的回答,基类已被标记为抽象,但构造函数仍被调用两次。是否还有其他原因可能会发生这种情况?可能值得注意的是,我在 faces-config.xml 中声明了我的 bean,而不是在从 1.2 迁移到 2.0 的过程中的注释。
    • @Lucas:使用 <h:someComponent binding="#{bean.component}"> 之类的组件绑定或 <f:validateLongRange minimum="#{bean.minimum}"> 之类的验证器/转换器属性或 <c:if test="#{bean.condition}"> 之类的 JSTL 标签将在每个请求上重建 bean。这是一个先有鸡还是先有蛋的问题:java.net/jira/browse/JAVASERVERFACES-1492 您可以通过关闭 web.xml 中的部分状态保存来解决。另请参阅我今天偶然回答的相关问题:stackoverflow.com/questions/7445417/…
    • @balusc 你说绑定 like binding... 除了binding 他们还能是什么?此外,我的网站由一个页面组成,该页面具有不同的页面块ui:included,当前渲染中未包含的binding 是否仍会导致此问题?
    • @卢卡斯:F5。我意识到这一点并且已经改进了评论。至于<ui:include>,在早期的 Mojarra 版本中也有类似的错误。确保您使用的是最新版本(2.0.6 或 2.1.3)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-11
    • 2019-05-09
    相关资源
    最近更新 更多