我有一个会话范围的 CDI 托管 bean:
@Named
@SessionScoped
public class SampleBean implements Serializable {
// ...
}
我需要在某个流程后从会话中删除此 bean,为此我使用了以下代码,如本答案所示:
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.getSessionMap().remove("sampleBean");
但是,它不起作用,SampleBean
保留在会话中。
我错过了什么吗?
与 JSF 管理的 Bean 相反,CDI 管理的 Bean 不是直接按其受管 Bean 名称存储在会话映射中。相反,它们由CDI管理器实现(Weld,OpenWebBeans等)使用会话ID作为密钥存储在服务器的内存中。
因此,您在那里使用的技巧不适用于 CDI 管理的 bean。您需要寻找替代方法。在这种特殊情况下,正确的方法是使用 @ConversationScoped
而不是 @SessionScoped
.在正确设计的 Web 应用程序中,永远不需要手动终止作用域。因此,首先使用@SessionScoped
进行对话/流已经是错误的。
@Inject
BeanManager beanManager;
.....
AlterableContext ctxSession = (AlterableContext) beanManager.getContext(SessionScoped.class);
for (Bean<?> bean : beanManager.getBeans(YourSessionBeanToBeDestroyedClass.class)) {
Object instance = ctxSession.get(bean);
if (instance != null)
ctxSession.destroy(bean);
}
这个¿?
面孔上下文 .getCurrentInstance() .getApplication() .createValueBinding( "#{yourBeanName}").setValue(FacesContext.getCurrentInstance(), null );