如何在后备 Bean 中检索 ui:param 的值

How to retrieve value of a ui:param in the backing bean

提问人:Mohsen 提问时间:1/22/2013 最后编辑:Mohsen 更新时间:10/17/2018 访问量:9782

问:

我正在将参数传递到另一个页面:p1page.xhtml

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

这是否可以评估@PostConstruct支持豆的方法内部?使用以下代码段,无法解析:#{p1}page.xhtml#{p1}

FacesContext currentInstance = FacesContext.getCurrentInstance();
currentInstance.getApplication().evaluateExpressionGet(currentInstance, "#{p1}", String.class);

我为什么需要这个?

我正在使用xhtml文件(例如component.xhtml)作为自定义UI组件。这个文件有一个后备 Bean,我应该从中获取组件数据。由于我在主 JSF 页面中包含此 xhtml 文件两次或更多次,因此我希望将不同的对象传递给每个 component.xhtml,以便我的组件每次都使用我的自定义数据。

JSF-2 参数 EL

评论

0赞 partlov 1/22/2013
此代码位于哪种后备 Bean 方法中?
0赞 Mohsen 1/22/2013
更新了我的问题:@PostConstruct方法。
0赞 partlov 1/22/2013
这可能是一个问题。@PostConstruct方法可以在构建页面之前执行。尝试定义 for 并查看它是否已解决。f:eventpreRenderView
0赞 Mohsen 1/22/2013
听起来很奇怪!preRenderView/preRenderComponent 侦听器未在包含的页面中调用。
0赞 Mohsen 1/22/2013
似乎这在包含的页面中不起作用。请参阅:stackoverflow.com/questions/12543405/...preRenderView

答:

11赞 BalusC 1/23/2013 #1

在 Mojarra 中,可以将其作为 FaceletContext 的属性获取。您可以在托管 Bean 中获取它,该 Bean 保证在包含的页面中首次被引用/构造(因此在组件树中声明之前不会在父页面中引用/构造)。@PostConstruct<ui:param>

FaceletContext faceletContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
Object p1 = faceletContext.getAttribute("p1");

在 MyFaces 中,整体在托管 Bean 中不可用,因为它在视图构建结束时被丢弃,然后此构造将不起作用。要独立于 JSF 实现,您可能需要考虑改为通过设置它。然后,它可作为请求属性使用。FaceletContext<c:set scope="request">

至于具体的功能要求,请考虑创建一个带有支持组件的复合组件。有关一些示例,请参阅我们的复合组件 wiki 页面和有关在复合组件中使用多个输入组件的博客。另请参阅何时使用 <ui:include>、标记文件、复合组件和/或自定义组件?

评论

0赞 Kenny Steegmans 12/3/2020
“保证在包含的页面中首次引用/构造的托管 Bean” 如果该页面与父页面同时加载,只要它从未在父页面中使用过,它应该仍然可以吗?还是我们需要延迟加载它来确保这一点?
0赞 BalusC 12/3/2020
如果你不能保证,就拆分成一个新的豆子。必要时,您可以轻松地注入“父”bean。
0赞 Kenny Steegmans 12/3/2020
好吧,我有一个专门用于我的复合体的 bean,但即使我延迟加载复合体(使用primefaces覆盖),我的参数也不会添加到上下文中。
0赞 BalusC 12/3/2020
复合?这不是“包含的页面”。请改用后备组件。另请参阅答案底部的链接。然后你可以简单地做一些类似 stackoverflow.com/q/21525669
1赞 Kenny Steegmans 12/4/2020
对不起,我的意思是构图而不是合成。(不确定区别,因为我从未使用过复合)
0赞 ravenskater 5/3/2017 #2

这对我有用:

<ui:include src="page.xhtml">
     <ui:param name="p1" value="#{someObject}"/>
</ui:include>

页面.xhtml:

<c:set var="data" value="#{p1}" scope="request"/>

你的豆子:

@ViewScoped
public class ManagedBean{

     private Object someObject;

     public Object getSomeObject(){
         if(someObject== null){
            HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
            someObject= request.getAttribute("data");
          }
          return someObject;
     }

     public void setSomeObject(Object someObject){
          this.someObject = someObject;
     }}
2赞 Bruno F 10/17/2018 #3

参数在 @PostConstruct 方法中不可用;您可以使用 preRenderComponent 事件来初始化后备 Bean 中的参数;只要把它放在包含页面的 ui:composition 之后,就会在包含页面本身的渲染之前执行。

遵循将 p1 参数传递给 page.xhtml 模板的 OP 示例

主页:

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

页面.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    ...>

<ui:composition>
    <f:event listener="#{backingBean.init(p1)}" type="preRenderComponent"/>
        ...

</ui:composition>

</html>

BackingBean.java:

@ViewScoped
 public class BackingBean{

     private Object p1;
     public void init(Object value){        
     this.p1=p1;
    }

    ...
 }

该事件在 UI:Composition 标记呈现之前触发,即在 Page.xHTML 呈现之前触发