JSF,facelets 上的 actionlistener

Posted

技术标签:

【中文标题】JSF,facelets 上的 actionlistener【英文标题】:JSF, actionlistener at facelets 【发布时间】:2011-02-10 19:33:14 【问题描述】:

我在一些用作 portlet 的 facelets 中使用 JSF (Mojarra 1.2) 和 Richfaces (3.3.2)(我在这里使用 Jboss Portlet Bridge 2.0)。现在我遇到了一些奇怪的事情:我的<h:commandButton> 上有一个actionlistener,当我点击按钮时触发了它,但是当我只是重新加载页面时,每次我再次加载页面时都会执行该操作。仅当我之前已触发该操作时才会发生这种情况。这种行为正常吗?

我应该注意到 Spring 2.5 用于管理我的 bean,提到的 bean 是会话范围的 bean,也许这是一个有趣的点?!

【问题讨论】:

【参考方案1】:

是的,重新加载 HTTP POST 请求将再次执行 HTTP POST 请求,从而再次触发所有相关的服务器端操作。此问题通常会影响所有 Web 应用程序,并且与 JSF 本身无关。

一个众所周知的解决方法是POST-Redirect-GET (PRG) pattern。基本上,您需要在处理完操作后立即将 POST 请求重定向到 GET 请求,以便通过 HTTP GET 请求传递结果页面。刷新此 HTTP GET 请求将不再执行初始 HTTP POST 请求。

然而,这种模式有一个警告:因为它涉及一个全新的请求,所有请求范围的 bean 都会被丢弃并在新请求中更新。因此,如果您想在新请求中保留数据,则需要将它们作为 GET 参数传递或将其存储在会话范围内。通常只需在 bean 的构造函数中重新加载数据就足够了。但是由于您提到仅使用会话范围的 bean(但这不是最佳实践,但除此之外),这对您来说应该不是一个大问题。

在 JSF 中开启 PRG 比较简单,只需在关联的<navigation-case> 中添加以下条目即可:

<redirect />

或者,如果您更喜欢以编程方式触发它,那么在 bean 的操作方法中使用 ExternalContext#redirect()

public void submit(ActionEvent event) 
    // ...
    FacesContext.getCurrentInstance().getExternalContext().redirect(someURL);

【讨论】:

感谢您的回复 BalusC - 但如果我只切换到另一个 portlet 页面,然后返回我的 JSF portlet,它仍然在会话 bean 中保存对象,那么操作也会执行。如果我没有完全错,这不应该发生,还是我错了? 一个注意事项:我在这里只使用会话范围的bean,因为它非常适合我的小portlet,它只显示一点点数据。好吧,我说的是复数形式,它只有一个带有一个支持 bean 的 JSF 页面。 你实现&lt;redirect /&gt;了吗? 否 - 万一我没有导航规则,我只需要一个页面,我用我的 dataTable 呈现面板组。问题是由这种情况引起的吗? 哦,它是基于 ajax 的请求吗?

以上是关于JSF,facelets 上的 actionlistener的主要内容,如果未能解决你的问题,请参考以下文章

正确使用 Facelet 模板和复合组件

JSF 2.0 和 Facelets

JSF/Facelets/JSTL 条件显示最佳实践

在 JSF2 项目中混合 JSP 和 XHTML (Facelets) - 可能吗?

找不到 http://java.sun.com/jsf/facelets 的标记库描述符

java中的Web开发存在哪些Spring+JSF/Facelets的替代品?