JSF组件的“ValueExpression Map”

时间:2011-10-07 07:53:24

标签: jsf

我将值表达式存储在带有f:attribute标记的JSF组件中,例如:

<h:inputText ...>
  <f:attribute name="myId1" value="#{bean.prop1}" />
  <f:attribute name="myId2" value="#{bean.prop2}" />
  <f:attribute name="myId3" value="#{bean.prop3}" />
</h:inputText>

有没有办法以编程方式访问所有这些值表达式? (没有知道名称myId1,myId2,...)

JSF 2.1规范的第9.4.2节说这些值存储在“组件的ValueExpression Map”中。 这是完整规范中唯一出现的“ValueExpression Map”一词。 我如何访问该地图?

在UI组件的Jboss / Mojarra实现的方法getValueExpression()中,地图

getStateHelper().get(UIComponentBase.PropertyKeys.bindings) 

用于获取单个值表达式。

我猜那张地图是“ValueExpression Map”的超级集合? 我可以确定所有实现和所有继承(标准)组件都使用该映射来存储ValueExpressions吗?

感谢。

3 个答案:

答案 0 :(得分:2)

理论中,您应该可以通过UIComponent#getAttributes()查看所有内容:

Map<String, Object> attributes = component.getAttributes();

for (Map.Entry<String, Object> entry : attributes.entrySet()) {
    System.out.printf("name=%s, value=%s%n", entry.getKey(), entry.getValue());
}

然而,这并不像你期望的那样有效。它只返回静态属性。这似乎永远不会被修复/实施。另见JSF issue 636。我建议坚持使用预定义前缀和增量数字后缀的attribtues,就像你在你的例子中所展示的那样。这也是我一直用于将组件中的其他信息传递给自定义验证器和转换器的内容。您可以按如下方式收集它们:

Map<String, Object> attributes = component.getAttributes();
List<Object> values = new ArrayList<Object>();

for (int i = 1; i < Integer.MAX_VALUE; i++) {
    Object value = attributes.get("myId" + i);
    if (value == null) break;
    values.add(value);
}

System.out.println(values);

答案 1 :(得分:1)

BalusC给出的答案的替代方法可能是使用嵌套构面或UIParameter组件。可以使用getFacets将构面检索为构图,但您可能需要在每个构面中放置一个额外的UIOutput来访问其值表达式。

可以通过迭代组件子项并检查instanceof UIParameter来访问嵌套UIParameters。 UIParameters具有namevalue属性,因此可以轻松转换为地图。

我在自定义组件中使用了参数,但我不确定示例中的标准UIInput如何对这些参数作出反应。

答案 2 :(得分:0)

BalusC是对的。 UIComponent#getAttributes()。get(name)从两个位置获取值 - 首先从属性映射获取,然后从“值表达式映射”中找不到。要设置一些值,您必须调用UIComponent#setValueExpression(name,ValueExpression)。如果value是literal,则将其存储到属性映射中,否则存储到“value expression map”中。一切都很好。