【问题标题】:Invoke JSF managed bean action on page load在页面加载时调用 JSF 托管 bean 操作
【发布时间】:2016-06-26 02:39:14
【问题描述】:

有没有办法在页面加载时执行 JSF 托管 bean 操作?

如果相关,我目前正在使用 JSF 1.2。

【问题讨论】:

标签: jsf action onload managed-bean


【解决方案1】:

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

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

【讨论】:

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

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

或者,使用&lt;f:event type="preRenderView"&gt; 以防您也打算基于&lt;f:viewParam&gt; 进行初始化,或者当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";
}

另见:

【讨论】:

  • 你的回答很好,适合我的需要...... 但是有一个问题...... 在我的 D. 构造函数中,我添加了这样一个内容,该内容将在视图中可见侧(在同一个jsp上)。在这种情况下,我的 jsp 不会第一次查看此信息。但是,如果我重新加载内容可见的页面。我们可以用任何方式处理这件事吗?
  • 如果我有一个会话范围,这个答案只会工作一次。有没有更好的方法来为会话范围 bean 实现这个?
  • @huahsin68,提供的答案将按预期工作。正如 BalusC 所说,对于范围比 view 范围更广的 bean,请使用最后两个示例。对于那些对在ui:composition 页面中放置f:metadata 信息的位置感到好奇的人:在ui:composition之前 可能的ui:define 或类似标签之后。
  • 如果你使用的是 jsf 2.0+,你应该使用 "f:event" 而不是 "f:viewAction"
【解决方案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】:

    @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 中完成工作。
    猜你喜欢
    • 2018-05-21
    • 2011-03-31
    • 1970-01-01
    • 2015-09-06
    • 2012-09-09
    • 1970-01-01
    • 2011-04-16
    相关资源
    最近更新 更多