在页面加载时调用 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+

或者,使用&lt;f:viewAction&gt; 以防您也打算基于&lt;f:viewParam&gt; 进行初始化,或者当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 DOM load 事件期间执行 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】:

&lt;p:remoteCommand&gt; 调用 bean 操作是个好主意,保留属性 autoRun="true" 下面的例子

<p:remoteCommand autoRun="true" name="myRemoteCommand" action="#bean.action" partialSubmit="true" update=":form" />

【讨论】:

当上述解决方案不需要额外的往返时,为什么这是一个“好主意”。

以上是关于在页面加载时调用 JSF 托管 bean 操作的主要内容,如果未能解决你的问题,请参考以下文章

javascript在启动时调用托管bean的方法,而不是在命令按钮单击时调用它们

如何从jsf / primefaces中的托管bean向页面添加组件[重复]

从视图范围的托管 bean JSF 填充数据表

JSF Spring Bean 设置属性

java jsf 如何去重新加载bean

JSF页面中给出的输入不会将该值设置为托管bean变量[duplicate]