多次调用 JSF Backing Bean 构造函数
Posted
技术标签:
【中文标题】多次调用 JSF Backing Bean 构造函数【英文标题】:JSF Backing Bean constructor called multiple times 【发布时间】:2011-06-17 02:48:51 【问题描述】:我正在尝试 JSF 2.0(在过去几个月使用 ICEfaces 1.8 之后)并且我试图弄清楚为什么在 JSF 2.0 中我的支持 bean 构造函数被多次调用。
bean 应该在创建时被实例化一次,但是每当我单击 commandButton 时都会显示“Bean Initialized”文本,表明正在实例化一个新的 Bean 对象。
facelet 页面:
<?xml version='1.0' encoding='UTF-8' ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:body>
<div id="content">
<h:form id="form">
<h:commandButton value="Toggle" action="#bean.toggleShowMe"/>
</h:form>
<h:panelGrid rendered="#bean.showMe">
<h:outputText value="Show me!"/>
</h:panelGrid>
</div>
</h:body>
</html>
支持 bean:
@ManagedBean
@RequestScoped
public class Bean
private boolean showMe = false;
public boolean isShowMe()
return showMe;
public void setShowMe(boolean showMe)
this.showMe = showMe;
public void toggleShowMe()
System.out.println(showMe);
if(showMe==true)
showMe=false;
else
showMe=true;
/** Creates a new instance of Bean */
public Bean()
System.out.println("Bean Initialized");
就是这样。只是一个简单的测试。如果我使用 ICEfaces 2.0 并代替我使用的 panelGrid,也会出现同样的行为:
<ice:panelPopup visible="#bean.showMe">
如果能提供任何帮助,我将不胜感激。我不知道怎么解释。
更新:作为对 Aba Dov 的回应,我对 bean 进行了@SessionScoped,认为它不会在每次请求时调用构造函数并遇到相同的行为。我错过了什么?
【问题讨论】:
如果组件是会话范围的,它不会在每个会话中创建超过一次——因为这种行为被广泛使用,错误可能在您的代码中,而不是 JSF;你在使用正确包中的@SessionScoped 吗? (EE6中有两个)。 fdreger-我正在使用 javax.faces.bean.SessionScoped。我应该使用 javax.enterprise.context.SessionScoped 吗? 【参考方案1】:您已声明要放置在请求范围内的 bean,并且每次都通过命令按钮触发一个新的 HTTP 请求。确实,每个请求都会创建 bean。
如果您希望 bean 的生命周期与视图本身一样长(就像 IceFaces 在幕后为所有 ajax 所做的那样),那么您需要声明 bean 视图的作用域(这是 JSF 2.0 中的新功能)。
@ManagedBean
@ViewScoped
public class Bean implements Serializable
【讨论】:
感谢您的解释!有用。有什么建议可以让您了解最新的 JSF 2.0 吗?规范阅读量很大。 还要注意涉及<c:forEach ...>
的代码和来自 bean 的列表。这将多次调用构造函数,即使 ViewScoped
@Chris:另见***.com/questions/2842401/…
@BalusC 我应该更详细地阅读该帖子,发现这很难。我确实有嵌套 ui:repeat (***.com/questions/3708490/…) 的问题。我真的很想看到 JSF 2.2 出来解决这些问题。
@Chris:<ui:repeat>
的状态管理在 Mojarra 中被严重破坏。使用 MyFaces 或以 UIData
风格提供它的第 3 方组件库(例如 <t:dataList>
)。【参考方案2】:
在我的情况下,问题是我导入了“javax.faces.bean.ViewScoped”而不是导入“javax.faces.view.ViewScoped”。
希望它可以帮助某人。
【讨论】:
如***.com/questions/5541813/…中提到的【参考方案3】:每次有来自页面的请求时都会调用 bean。
当您单击<h:commandButton>
时,表单已提交并向服务器发送请求
为了防止它,您可以使用<t:saveState>
或<a4j:keepAlive>
标记。
例如<a4j:keepAlive beanName="YourBean" />
这些标签将 bean 实例存储在组件树中。
还要确保您的班级implements Serializable
。所以可以序列化
希望对你有帮助
【讨论】:
在 JSF 2 中,viewscope 执行 keepAlive 或 saveState 的工作【参考方案4】:bean 应该在 ViewScoped 中。
【讨论】:
如果您不需要将数据保存这么长时间怎么办.. viewScoped 可以工作但不是免费的,它会消耗您服务器上的内存,为什么您需要将不必要的数据保存这么长时间?由于 bean 已经请求了数据,因此将数据保留在视图范围内有什么意义,以及为什么 JSF 需要在按下 commmandButton 时在视图中创建所有托管 bean,为什么不只是actionListener bean 被实例化了?以上是关于多次调用 JSF Backing Bean 构造函数的主要内容,如果未能解决你的问题,请参考以下文章