8

我在 JSF 2.0 中构建了一个自定义组件

标签如下所示:

<x:myTag id="1" name="AAA" />

对应的java类:

@FacesComponent("a.b.c.MyTag")
public class UIMyTag extends UIInput {

   private String name;
   private String id;

   public String getId() {
      return id;
   }

   public void setId(String id) {
       this.id = id;
   }


   public String getId() {
      return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   @Override
   public void encodeBegin(FacesContext context) throws IOException {
       ResponseWriter writer = context.getResponseWriter();
       logger.debug(getName()); //prints null for name="#{dummyBean.name}" 
                                //   and AAA for name="AAA"
       logger.debug(getAttributes().get("name")); // always correct value
   ...
}
   ....

}

如果我使用

<x:myTag id="1" name="AAA" />

一切都按预期工作,但是当我将 EL 用于 myTag 属性时,该setName()方法永远不会被调用。因此对于,

<x:myTag id="#{dummyBean.id}" name="#{dummyBean.name}" />

我总是在我的方法中null获取name属性。encodeBegin调试后,我注意到该setName方法永远不会被调用。我认为可能关于 EL 的某些事情会搞砸(我仍然相信原因与此有关),但真正奇怪的是该id属性运行良好:setter 被调用,并且在 econding 开始时值与预期一致.

我不得不提一下,如果我getAttributes().get("name")encodeBegin方法调用我会得到正确的名称值,但我很好奇为什么它不适用于 getter 和 setter。

任何想法我的组件缺少什么?

4

1 回答 1

12

这种行为是预期的并且是规范的。作为值表达式的属性值由 设置UIComponent#setValueExpression()。它们应该只在真正被使用时才被评估,通常是在视图渲染期间。

( idand binding) 属性有特殊处理:它在视图构建期间在设置之前进行评估,因此将调用“常规”设置器而不是(因为当(or ) 属性动态评估为时,视图的setValueExpression()渲染会崩溃由于某种原因,与视图构建期间的值不同)。idbinding

更好的是将 getter/setter 委托UIComponent#getStateHelper()给本地属性而不是本地属性。setValueExpression()最终也StateHelper以. _getAttributes()StateHelper

public String getName() {
   return (String) getStateHelper().eval("name");
}

public void setName(String name) {
    getStateHelper().put("name", name);
}

请注意,您可以安全地删除andgetId()方法setId(),因为它们已经在UIComponentBase您要扩展的超类中定义。

于 2012-08-08T16:13:56.330 回答