JSF Bean:在设置ViewParam之后调用@PostConstruct函数

12
我有一个 product.xhtml 文件和一个 ProductBean。我使用 /product/{id} 访问产品,因此在 product.xhtml 中使用了一个 viewParam,其 value=ProductBean.id。问题在于,我在 bean 内部使用了一个带有 PostConstruct 注释的 init 函数,以填充产品的详细信息。为此,我需要 id 调用外部函数。我猜测 init 在 viewParam 设置 bean 的 id 之前就被调用了,因此在 init 中我无法调用外部函数,因为 id 还没有设置。我做错了什么,该如何解决?

更新

我找到了问题所在。我认为 viewParam 方法适用于 CDI bean,而 ManagedProperty 方法适用于 JSF bean。

现在我还有另一个问题。我的 CDI bean 是 RequestScoped 的,当渲染 product.xhtml 时,bean 被创建,然后会被丢弃。有趣的是,我在该 bean 中有一个函数,在调用时,可以读取 id(我假设这是因为与 view param 相关),但不能读取任何其他属性。有什么办法解决这个问题?


1
关于您的更新,您关于viewParam的陈述是错误的。<f:viewParam>不特定于CDI。无论谁管理bean,它都可以工作。@ManagedProperty确实仅在JSF @ManagedBean中起作用,但这不过是显而易见的,因为@ManagedProperty是JSF特定的注释,而不是CDI特定的注释。 - BalusC
1个回答

27

你需要使用<f:event type="preRenderView">而不是其他标签。

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:event type="preRenderView" listener="#{bean.onload}" />
</f:metadata>

使用

public void onload() {
    // ...
}

请注意,这本质上是一个小技巧。即将推出的JSF 2.2将提供一个新的、更合理的标签来实现这个唯一目的:<f:viewAction>

<f:metadata>
    <f:viewParam name="foo" value="#{bean.foo}" />
    <f:viewAction action="#{bean.onload}" />
</f:metadata>

另请参阅:


我无法使用您发布的第一个链接中的第一种方法使其工作,但我可以使用第二种方法使其工作。不过,我理解第一种方法比第二种更好,这是正确的吗? - user579674
2
这里的想法是完全跳过@PostConstruct注释,依靠从preRenderView调用的init吗? - Aksel Willgert
由于我的f:event在postback时也会被调用,我不得不添加一个标志来判断初始化是否已经完成。是否有可能像@PostConstruct一样只调用该事件一次? - Danubian Sailor
但是preRender在每个请求(postback ajax或正常postaback)上都会被调用。所以您建议在每个请求上重新初始化您的bean吗?问题是JSF托管的bean和CDI bean是两个不同的世界(容器)汇集在一起。它们可以共存,但代码充满了hack。我怀疑任何新版本的JSF或CDI都无法解决问题,因为混合两个不同的组件模型总是很麻烦的工作。 - Mitja Gustin
@MitjaGustin:确实,还可以参考https://dev59.com/Nmw15IYBdhLWcg3w0fEV。但是OP有一个请求范围的bean,而不是视图范围的bean。因此,这些额外的检查是不必要的。只需升级到JSF 2.2并获取<f:viewAction>即可。 - BalusC
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接