何时使用 f:viewAction / preRenderView 与 PostConstruct?

Posted

技术标签:

【中文标题】何时使用 f:viewAction / preRenderView 与 PostConstruct?【英文标题】:When to use f:viewAction / preRenderView versus PostConstruct? 【发布时间】:2012-04-08 07:51:30 【问题描述】:

什么时候应该使用f:viewActionpreRenderView 事件来初始化页面的数据而不是使用@PostConstruct 注释?是否基于支持 bean 的范围类型使用其中一个或另一个的基本原理,例如如果支持 bean 是 @RequestScoped,那么在渲染视图之前选择使用 f:viewActionpreRenderView 而不是 @PostConstruct 来初始化支持 bean 是否无关紧要,因为两者会产生相同的效果?

f:viewAction 或 preRenderView

<f:metadata>
  <f:viewAction action="#myBean.initialize" />
</f:metadata>
<f:metadata>
  <f:event type="preRenderView" listener="#myBean.initialize"/>
</f:metadata>

@PostConstruct

public class MyBean

    @PostConstruct
    public void initialize()
    

    

【问题讨论】:

【参考方案1】:

什么时候应该使用 f:viewAction 或 preRenderView 事件来初始化页面的数据,而不是使用 @PostConstruct 注解?

如果您想在呈现 html 之前执行方法,请使用 &lt;f:viewAction&gt;。如果您想在更新模型值阶段根据&lt;f:viewParam&gt; 设置的模型值执行操作,这将特别有用。也就是说,它们在@PostConstruct 运行时不可用。在 JSF 2.0/2.1 中,此标记不存在,您必须使用 preRenderView 解决方法。

如果支持 bean 是 @RequestScoped,它们是否有效地做完全相同的事情? (所以这取决于开发人员的选择?(@PostConstruct 似乎“更干净”)。

不,他们肯定不会有效地做同样的事情。 @PostConstruct 旨在在 bean 构造和设置所有注入的依赖项和托管属性(例如 @EJB@Inject@ManagedProperty 等)之后执行操作直接。即注入的依赖项在 bean 的构造函数中不可用。因此,当 bean 是视图、会话或应用程序范围时,每个视图、会话或应用程序将只运行一次。 &lt;f:viewAction&gt; 默认情况下仅在初始 GET 请求时调用,但也可以通过 onPostback="true" 属性配置为在回发请求时调用。在每个 HTTP 请求上都会调用 preRenderView 事件(是的,这也包括 ajax 请求!)。

总结一下,如果你想在 bean 的构建过程中对注入的依赖项和由@EJB@Inject@ManagedProperty 等设置的托管属性执行操作,请使用 @PostConstruct。如果您想对&lt;f:viewParam&gt; 设置的属性执行操作,请使用&lt;f:viewAction&gt;。如果您仍在使用 JSF 2.0/2.1,请使用 preRenderView 而不是 &lt;f:viewAction&gt;。如有必要,您可以在 FacesContext#isPostback() 上添加检查,以仅在初始请求时执行 preRenderView 操作。

另见:

What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for? ViewParam vs @ManagedProperty(value = "#param.id") Is it possible to disable f:event type="preRenderView" listener on postback?

【讨论】:

谢谢。抱歉,我在您写回复时编辑了我原来的问题... 我提到了 bean 范围,因为如果 bean 是 SessionScoped(在第一次创建 bean 时),@PostConstruct 只会被调用一次,但每次访问页面时都会调用 preRenderView。还是我弄错了? 是的,没错。在调用动作阶段调用预渲染视图事件。 post 构造在 bean 构造之后被调用。不是在每个 HTTP 请求上都构建会话范围的 bean。 我想知道我的方法在 ajax 请求期间被调用。 isPostBack() 调用拯救了这一天!! 为了完整起见,我们应该提到Omnifaces' @Param:“对于HTTP请求参数,它基本上类似于&lt;f:viewParam&gt;,但主要区别在于注入参数在@PostConstruct期间直接可用,无需在视图中使用&lt;f:event type="preRenderView"&gt;&lt;f:viewAction&gt;,就可以更轻松地进行处理。"【参考方案2】:

您需要初始化托管 bean 的属性吗? --> 然后,使用@PostConstruct 否则,您是否需要使用从其他视图传递的参数? --> 然后,使用“preRenderView

【讨论】:

以上是关于何时使用 f:viewAction / preRenderView 与 PostConstruct?的主要内容,如果未能解决你的问题,请参考以下文章

在使用 p:commandButton 导航时调用 f:viewAction 中的操作

f viewaction 中的 f ajax 之类的东西?

根据 f:viewParam 有条件地调用 f:viewAction

f:viewAction 被忽略,当 commandButton 导航到页面时

有没有办法以编程方式检测用户何时按下浏览器中的F5按钮?

当与查询参数关联的转换/验证失败时执行重定向