我正在尝试使用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,我@SessionScoped bean,认为它不会在每次请求时调用构造函数并遇到相同的行为。我错过了什么?
答案 0 :(得分:6)
您已将bean声明放在请求范围内,并且每次都通过命令按钮触发新的HTTP请求。确实会在每次请求时创建bean。
如果你想让bean一直存在于视图本身(就像IceFaces正在为所有ajax的东西做掩盖),那么你需要声明bean视图范围(这是JSF 2.0中的新特性)。
@ManagedBean
@ViewScoped
public class Bean implements Serializable {}
答案 1 :(得分:1)
在我的情况下,问题是我导入了“ javax.faces.bean.ViewScoped”,而不是导入了“ javax.faces.view.ViewScoped”。
希望它可以帮助某人。
答案 2 :(得分:0)
每次有来自页面的请求时都会调用bean。
当您单击<h:commandButton>
提交表单并将请求发送到服务器
为了防止它,您可以使用<t:saveState>
或<a4j:keepAlive>
标记。
例如<a4j:keepAlive beanName="YourBean" />
这些标记将bean实例存储在组件树中。
还要确保您的班级implements Serializable
。所以可以序列化
希望这有帮助
答案 3 :(得分:0)
bean应该在ViewScoped中。