在页面加载时调用 JSF 托管 bean 操作
Posted
技术标签:
【中文标题】在页面加载时调用 JSF 托管 bean 操作【英文标题】:Invoke JSF managed bean action on page load 【发布时间】:2011-01-27 21:54:53 【问题描述】:有没有办法在页面加载时执行 JSF 托管 bean 操作?
如果相关,我目前正在使用 JSF 1.2。
【问题讨论】:
重复***.com/questions/1686821/… 虽然不确定,但问题有歧义。只要他没有明确说明“在页面加载时下载文件”,或者“在页面加载时触发新请求”等,那么所提到的主题就不一定是这个问题。 这里给出正确答案***.com/a/1710413/362752 【参考方案1】:JSF 1.0 / 1.1
只需将所需的逻辑放入与 JSF 页面关联的请求范围 bean 的构造函数中即可。
public Bean()
// Do your stuff here.
JSF 1.2 / 2.x
在请求或视图范围 bean 上使用 @PostConstruct
注释方法。它将在构造和所有托管属性和注入的依赖项的初始化/设置之后执行。
@PostConstruct
public void init()
// Do your stuff here.
如果您使用的是使用代理(例如 CDI)的 bean 管理框架,强烈建议使用此方法而不是构造函数,因为构造函数可能不会在您期望的时间被调用。
JSF 2.0 / 2.1
或者,使用<f:event type="preRenderView">
以防您也打算基于<f:viewParam>
进行初始化,或者当bean 放置在比视图范围更广的范围内(这反过来表明存在设计问题,但除此之外)。否则,@PostConstruct
也可以。
<f:metadata>
<f:viewParam name="foo" value="#bean.foo" />
<f:event type="preRenderView" listener="#bean.onload" />
</f:metadata>
public void onload()
// Do your stuff here.
JSF 2.2+
或者,使用<f:viewAction>
以防您也打算基于<f:viewParam>
进行初始化,或者当bean 放置在比视图范围更广的范围内(这反过来表明存在设计问题,但除此之外)。否则,@PostConstruct
也可以。
<f:metadata>
<f:viewParam name="foo" value="#bean.foo" />
<f:viewAction action="#bean.onload" />
</f:metadata>
public void onload()
// Do your stuff here.
请注意,如有必要,这可以返回 String
导航案例。它将被解释为重定向(因此您在这里不需要?faces-redirect=true
)。
public String onload()
// Do your stuff here.
// ...
return "some.xhtml";
另见:
How do I process GET query string URL parameters in backing bean on page load? What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for? How to invoke a JSF managed bean on a HTML DOM event using native javascript? - 如果您真的有兴趣在 HTML DOMload
事件期间执行 bean 操作方法,而不是在页面加载期间。
【讨论】:
你的回答很好,适合我的需要...... 但是有一个问题...... 在我的 D. 构造函数中,我添加了这样一个内容,该内容将在视图中可见侧(在同一个jsp上)。在这种情况下,我的 jsp 不会第一次查看此信息。但是,如果我重新加载内容可见的页面。我们可以用任何方式处理这件事吗? 如果我有一个会话范围,这个答案只会工作一次。有没有更好的方法来为会话范围 bean 实现这个? @huahsin68,提供的答案将按预期工作。正如 BalusC 所说,对于范围比 view 范围更广的 bean,请使用最后两个示例。对于那些对在ui:composition
页面中放置f:metadata
信息的位置感到好奇的人:在ui:composition
和之前 可能的ui:define
或类似标签之后。
如果你使用的是 jsf 2.0+,你应该使用 "f:event" 而不是 "f:viewAction"【参考方案2】:
@PostConstruct 在创建 Bean 时首先运行一次。 解决方案是创建一个未使用的属性并在该属性的 Getter 方法中执行您的操作 并将此属性添加到您的 .xhtml 文件中,如下所示:
<h:inputHidden value="#loginBean.loginStatus"/>
在你的 bean 代码中:
public void setLoginStatus(String loginStatus)
this.loginStatus = loginStatus;
public String getLoginStatus()
// Do your stuff here.
return loginStatus;
【讨论】:
那么,您正在使用单独的会话范围 bean?这是一个不好的做法。另外,你的例子很糟糕。 Getter 可以在 bean 的生命中不止一次被调用,并且不应该被滥用来执行业务。只需使用请求范围的 bean 并在构造函数或@PostConstruct
中完成工作。【参考方案3】:
另一个简单的方法是在视图渲染之前使用 fire 方法。这比 postConstruct 更好,因为对于 sessionScope,postConstruct 只会在每个会话中触发一次。每次加载页面时都会触发。当然,这仅适用于 JSF 2.0,不适用于 JSF 1.2。
这是怎么做的-
<html xmlns:f="http://java.sun.com/jsf/core">
<f:metadata>
<f:event type="preRenderView" listener="#myController.onPageLoad"/>
</f:metadata>
</html>
并且在 myController.java
public void onPageLoad()
// Do something
编辑 - 虽然这不是此页面上问题的解决方案,但我仅为使用更高版本 JSF 的人添加此内容。
JSF 2.2 有一个新功能,它使用viewAction
执行此任务。
<f:metadata>
<f:viewAction action="#myController.onPageLoad" />
</f:metadata>
【讨论】:
【参考方案4】:从<p:remoteCommand>
调用 bean 操作是个好主意,保留属性 autoRun="true"
下面的例子
<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#bean.action" partialSubmit="true" update=":form" />
【讨论】:
当上述解决方案不需要额外的往返时,为什么这是一个“好主意”。以上是关于在页面加载时调用 JSF 托管 bean 操作的主要内容,如果未能解决你的问题,请参考以下文章
javascript在启动时调用托管bean的方法,而不是在命令按钮单击时调用它们