Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jsf 2 如何(何时?)在JSF2.0中删除会话范围的bean_Jsf 2 - Fatal编程技术网

Jsf 2 如何(何时?)在JSF2.0中删除会话范围的bean

Jsf 2 如何(何时?)在JSF2.0中删除会话范围的bean,jsf-2,Jsf 2,背景:我有一个使用MyFaces的JSF2.0应用程序。使用这个应用程序,用户将通过浏览大量不同的JSF页面来创建一个复杂的“小部件”。我将托管bean存储在会话作用域中,并且在用户浏览每个页面时填充属性。一旦组装好“小部件”,他们就会想要创建一个全新的“小部件”,并重复这个过程。我的问题是,如何在不中断JSF生命周期的情况下从会话中完全(安全地)删除托管bean 我看到了其他类似问题的回答,建议您可以使会话无效,也可以通过FacesContext访问HttpSession并以这种方式删除bea

背景:我有一个使用MyFaces的JSF2.0应用程序。使用这个应用程序,用户将通过浏览大量不同的JSF页面来创建一个复杂的“小部件”。我将托管bean存储在会话作用域中,并且在用户浏览每个页面时填充属性。一旦组装好“小部件”,他们就会想要创建一个全新的“小部件”,并重复这个过程。我的问题是,如何在不中断JSF生命周期的情况下从会话中完全(安全地)删除托管bean

我看到了其他类似问题的回答,建议您可以使会话无效,也可以通过FacesContext访问HttpSession并以这种方式删除bean。我不希望用户必须注销或再次登录,也不希望使整个会话无效。假设我需要通过FacesContext访问HttpSession并删除bean,那么在JSF生命周期中,什么时候是最适合安全地执行此操作的地方,这样问题就不会在循环的其余部分级联?我想确保当用户开始创建下一个“小部件”的过程时,JSF在创建新的会话bean时不会出现问题

我也很想理解为什么JSF中没有一种机制使这变得更容易。我是否应该采取其他更符合预期JSF模式的方法?我不能在这里使用视图范围,因为托管bean在完成之前将遍历几个不同的页面和视图


提前谢谢

虽然我自己还没有使用过它,但我想看看CDI的
ConversationScope

如果小部件创建数据被封装到单个bean中,您的案例可以简化。 我是说

对于视图中的resetWidget(仅在第一个widget创建页面中)


你可以使用指针并进行相应的调整


希望这有帮助。

创建一个页面,在其中有条件地呈现多个向导步骤

<h:panelGroup rendered="#{wizard.step == 1}">
   <ui:include src="/WEB-INF/wizard/step1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 2}">
   <ui:include src="/WEB-INF/wizard/step2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 3}">
   <ui:include src="/WEB-INF/wizard/step3.xhtml" />
</h:panelGroup>

这样,您就可以在这个页面上使用
@ViewScoped
托管bean,而无需太多麻烦



与具体问题无关的,有一个组件几乎与之完全相同。您可能会发现,它非常有用,可以避免您在验证等方面遇到一些麻烦的样板代码。

我同意BalusC的观点,在您的情况下,视图范围将是更好的选择。我只是查看了我的(非常旧的)第一个JSF项目,在该项目中,会话范围中有一个多页表单。后来,出于众所周知的原因,我切换到查看状态

但是,我确实通过简单地替换会话映射中的实例重置了会话范围bean:

MyBean newInstance=newmybean();
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().put(beanName,newInstance);

使用
beanName
作为bean的el名称(一个字符串)。

如果最终用户在多步骤过程的中途在新的浏览器选项卡中打开widtget页面,该怎么办?当然,这两个选项卡/窗口会相互干扰。@BalusC只是按照描述回答,这个陷阱是显而易见的,同意我的情况,我在请求范围内有一个控制器/支持bean,做一些像EntityManager活动这样通常不线程安全的事情。会话bean被注入其中。有了这种设计,preRenderView会是一个安全的地方来运行一个方法来消除会话bean吗?@tcprogrammer你能发布一些代码来帮助我吗,但就我所能想象的,entitymanager应该驻留在一个存储库/dao bean中,根据Spring语义,它是单例的,您只是在服务bean中使用了存储库,但从未满足将其替换或放入会话作用域的需要,代码示例可能会有所帮助,因为您可能使用了错误的作用域。@gbagga控制器bean在请求作用域中,而实体/模型bean在会话作用域中。唯一使用EntityManager的代码在控制器bean中,它安全地位于请求范围内。这不是一个Spring应用程序,它是带有本地事务的纯JPA(EclipseLink)。我会看看是否可以创建一个简单的示例发布在这里。谢谢BalusC,我认为这在我现在的情况下可能会起作用。在更复杂的应用程序中,这可能会有更大的问题。处理会话bean真的有那么麻烦吗?我最终在这方面使用了ViewScope bean。谢谢正如我在文章中提到的,我知道如何在会话映射中访问bean,但是,在JSF生命周期中,您到底在哪里执行此操作以确保安全?我使用命令按钮操作方法来执行此操作,而不关心这是否是正确的阶段。现在使用的是servlet容器,而不是完整的J2EE容器,但我会记住这一点,以备将来考虑。您可以通过将CDI添加到任何servlet容器中。
<f:metadata>
  <f:event type="preRenderView" listener="#{widgetMaker.resetWidget}"/>
</f:metadata>
<h:panelGroup rendered="#{wizard.step == 1}">
   <ui:include src="/WEB-INF/wizard/step1.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 2}">
   <ui:include src="/WEB-INF/wizard/step2.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{wizard.step == 3}">
   <ui:include src="/WEB-INF/wizard/step3.xhtml" />
</h:panelGroup>