JSF 中的 EL 可变分辨率:有没有办法控制它何时发生



我经常面临以下问题。我有一个JSF应用程序和一个facelet,我在其中编写EL表达式,如下所示:

<h:outputText value="#{myBean.foo}">

只要myBean作为一个变量的生命周期足够长,在任何给定时间评估myBean.foo都没有问题,但如果myBean变量是在短时间内引用某个 bean 的变量,那么当myBean.foo被计算时可能为时已晚,因此 JSF 抱怨myBean解析为null。这是众所周知的,但问题是我不清楚在不同情况下会发生什么。

具体示例 1:如果您使用 PrimeFaces OrderList 尝试以下操作:

<p:orderList value="#{bean.myValue}" var="item">
  <p:column>
    <p:commandLink action="#{bean.doSomething(item)}" />
  </p:column>
</p:orderList>`

这是行不通的,因为当调用doSomething时,不再定义item变量(尽管它引用的对象仍然活着(,因此它被解析为null。这是一个已知问题。但是,例如,相同的模式适用于<p:dataTable>。无论如何,我现在对这个具体问题不感兴趣,我只想解释一下我的疑问。

具体示例 n. 2:我编写了一个带有背衬 bean 的复合组件。后备 Bean 扩展UINamingContainer并使用其StateHelper来保留模型对象。这个复合允许编写子标签,我想写这样的东西:

<myns:myCc var="myVar">
  <h:inputText value="#{myVar.foo}" />
</myns>

使用"myVar",我想为模型对象命名。为了完成这项工作,我尝试在方法开始时将模型对象存储在请求映射中encodeChildren然后删除它:这适用于渲染,但是如果我随后使用 commandButton 操作处理输入,它不起作用,因为当操作执行时,它说myVar无法解析: 换句话说,它试图解决整个表达式为时已晚。然后,我尝试将模型对象"永久"保存在视图范围图中,但它也不起作用。但是,如果我将其更改为:

(假设modelObject是存储我的模型对象的后备 Bean 中的属性字段(它有效。因此,在我的模型中这不是问题,而是我尝试使模型对象可用于子标记的 EL 表达式的方式。

具体示例 3:我经常使用 <ui:param> 标签给 bean 一个更短的名字,并简化模板化。例如:

<ui:param name="bean" value="#{longNamedAndPageSpecificBean}" />

因此,在页面的其余部分中,我只能使用#{bean.foo}而不是#{longNamedAndPageSpecificBean.foo}。即使对于传递给命令按钮的操作,这也工作正常。但是,如果我将像 #{bean.myActionMethod} 这样的方法表达式传递给用 method-signature 声明的复合组件属性,当实际调用此方法表达式时,我会收到一个错误,bean解析为null......它之所以在一种情况下(使用命令按钮操作(而不适用于另一种情况(使用复合组件使用的操作(的原因对我来说是一个很大的困惑来源。

如果有人能帮助我更好地理解这个 JSF 方面,并通过上述具体示例提出更好的方法/解决方法,我将不胜感激。

您的问题看起来太大了,但我可以说,在构建期间,只有会话和请求范围的值可用。

执行阶段也是如此。

只有渲染阶段才能确保临时变量"myVar"的可用性。

了解其实际发生情况的最佳方法是调试,因为它取决于组件实现

最新更新