标注@Scope(ScopeType.CONVERSATION)的Seam Bean表现如请求作用域的问题
问题分析与解决方案
核心问题
你的ActionBean使用了ScopeType.CONVERSATION(对话作用域),但对话未正确开启,导致每次AJAX请求都会创建一个新的Bean实例,因此list每次都是新初始化的ArrayList,每次添加后size始终为1。
原因详解
Seam的对话作用域默认不会自动激活,除非显式开启对话。如果没有开启对话,Seam会将对话作用域的Bean当作请求作用域处理——每次HTTP请求(包括AJAX请求)都会创建新的Bean实例,原有的list自然无法保留。
解决方案
在触发对话的方法上添加@Begin注解,确保第一次请求时开启对话,后续请求复用同一个Bean实例。
修改后的ActionBean代码
import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.jboss.seam.annotations.Begin; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.ScopeType; import jp.co.dir.bf.common.AppLogger; import jp.co.dir.bf.front.common.BaseBean; @Scope(ScopeType.CONVERSATION) @Name("ActionBean") public class ActionBean extends BaseBean { private AppLogger appLogger; private List<String> list = new ArrayList<>(); public ActionBean() { appLogger = new AppLogger(Logger.getLogger(ActionBean.class)); } @Begin // 页面加载时开启对话 public void init(){ appLogger.showDebug("The Form is loaded"); appLogger.showDebug("Initial Size: " + list.size()); } public AppLogger getAppLogger() { return appLogger; } public void setAppLogger(AppLogger appLogger) { this.appLogger = appLogger; } public List<String> getList(){ return list; } @Begin(join = true) // 如果init没触发,点击按钮时开启或加入已有对话 public void addToList(){ list.add("New Item"); appLogger.showDebug("Item added: " + list.size()); } public void setList(List<String> list){ this.list = list; } }
补充说明
@Begin注解的join = true参数确保如果对话已经存在,当前请求会加入该对话,而不是创建新的。- 确保页面初始化时调用了
init()方法(比如通过<f:event type="preRenderView" listener="#{ActionBean.init}"/>),这样页面加载时就开启对话,避免第一次点击按钮才创建对话的情况。
内容的提问来源于stack exchange,提问作者jironemo
相关产品推荐
相关产品推荐

