我在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被调用,值为as在经济开始时预期。
我必须提一下,如果我从getAttributes().get("name")
方法调用encodeBegin
,我会得到正确的名称值,但我很感兴趣为什么它不适用于getter和setter。
我的组件缺少什么想法?
答案 0 :(得分:12)
此行为是预期的并且符合规范。作为值表达式的属性值由UIComponent#setValueExpression()
设置。它们应该仅在它们真正使用时才被评估,通常在视图渲染时间期间。
id
(和binding
)属性有特殊处理:在设置之前在视图构建时期间对其进行评估,因此将调用“常规”setter setValueExpression()
的{{1}}(因为id
(或binding
)属性动态评估的值与视图构建时的值不同,因此视图的渲染会因某种原因而崩溃)
最好是将getter / setter委托给UIComponent#getStateHelper()
而不是本地属性。 setValueExpression()
最终也会在StateHelper
中结束(请注意,它根本不会调用setter;只要在需要数据时调用getter),getAttributes()
也会解析来自StateHelper
。
public String getName() {
return (String) getStateHelper().eval("name");
}
public void setName(String name) {
getStateHelper().put("name", name);
}
请注意,您可以安全地删除 getId()
和setId()
方法,因为它们已经在您正在扩展的UIComponentBase
超类中定义