<f:attribute value =“#{some EL expression}”>找不到通过getAttributes()。containsKey()</f:attribute>

时间:2014-09-03 07:44:29

标签: jsf jsf-2 attributes el

我无法在ViewHandler内检索包含EL的属性。

作为一个最小的例子,这是我的ViewHandler。它只查找属性"attributeName"并打印出其值。

public class MiniViewHandler extends ViewHandlerWrapper
{
  private ViewHandler defaultViewHandler = null;

  public MiniViewHandler()
  {
  }

  public MiniViewHandler(ViewHandler defaultViewHandler)
  {
    super();
    this.defaultViewHandler = defaultViewHandler;
  }

  @Override
  public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException
  {
    viewToRender.visitTree(VisitContext.createVisitContext(context),
            new VisitCallback()
            {

              @Override
              public VisitResult visit(VisitContext context, UIComponent target)
              {
                if (target.getAttributes().containsKey("attributeName"))
                {
                  System.out.println("Found it: " + target.getAttributes().get("attributeName"));
                }

                return VisitResult.ACCEPT;
              }
            }
    );

    defaultViewHandler.renderView(context, viewToRender);
  }

  @Override
  public ViewHandler getWrapped()
  {
    return defaultViewHandler;
  }
}

这是在faces-config.xml中注册的。我正在打的xhtml:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<h:body>
    <f:view>
        <f:attribute name="attributeName" value="#{2 + 5}"/>
    </f:view>
    <f:view>
        <f:attribute name="attributeName" value="2 + 5"/>
    </f:view>
</h:body>
</html>

记录的输出显示仅拾取了非EL属性。

INFO  [stdout] (http-/127.0.0.1:8080-1) Found it: 2 + 5

1 个答案:

答案 0 :(得分:3)

错误在于:

if (target.getAttributes().containsKey("attributeName"))

您正在使用containsKey()检查是否已指定该属性。但是,如果属性为ValueExpression,则无法使用此功能。这是UIComponent#getAttributes() javadoc的摘录,重点是:

  

的getAttributes

     

public abstract java.util.Map<java.lang.String,java.lang.Object> getAttributes()

     

返回一个变量Map,表示与UIComponent相关联的属性(和属性,见下文),由属性名称(必须是String)键入。返回的实现必须支持所有标准和可选的Map方法,并支持以下附加要求:

     
      
  • Map实现必须实现java.io.Serializable接口。
  •   
  • 任何添加null键或值的尝试都必须抛出NullPointerException
  •   
  • 任何添加非String密钥的尝试都必须抛出ClassCastException
  •   
  • 如果指定为键的属性名称与此UIComponent实现类的属性匹配,则以下方法将具有特殊行为:   
        
    • containsKey() - 返回false
    •   
    • get() - 如果属性是可读的,则调用getter方法并返回返回的值(将原始值包装在相应的包装类中);否则抛出IllegalArgumentException
    •   
    • put() - 如果属性是可写的,则调用setter方法设置相应的值(在相应的包装类中展开原始值)。如果该属性不可写,或者尝试将基本类型的属性设置为null,则抛出IllegalArgumentException
    •   
    • remove() - 抛出IllegalArgumentException
    •   
  •   

因此,它总是为false返回containsKey的组件属性(读取:组件&#39; s ValueExpression s)。这是因为动态属性不存储在属性映射中,而是存储在组件实例中,通过UIComponent#setValueExpression()调用。他们只在致电get()时才解决。

你基本上需要改变错误的行,如下所示,这也适用于&#34;静态&#34;属性:

Object value = target.getAttributes().get("attributeName");
if (value != null) {
    System.out.println("Found it: " + value);
}

如果您想检查该属性是否实际设置,即使它会评估null value="#{bean.returnsNull}",那么您更愿意检查UIComponent#getValueExpression()不会返回null

if (target.getValueExpression("attributeName") != null) {
    System.out.println("Found it: " + target.getAttributes().get("attributeName"));
}

但这反过来又不适用于&#34;静态&#34;属性。如有必要,您可以根据具体的功能要求组合检查。