我有一个复合组件:
<cc:interface componentType="com.example.MyComponent">
<!-- ... -->
</cc:interface>
<cc:implementation>
<f:phaseListener binding="#{cc}"/>
<div id="#{cc.clientId}">
<!-- ... -->
</div>
</cc:implementation>
及其班级:
@FacesComponent("com.example.MyComponent")
public class MyComponent extends UIOutput implements NamingContainer, PhaseListener
{
@Override
public String getFamily()
{
return "javax.faces.NamingContainer";
}
@Override
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
@Override
public void beforePhase(PhaseEvent event)
{
// Do something ...
}
@Override
public void afterPhase(PhaseEvent event)
{
// Do something ...
}
}
在任何情况下都不会调用beforePhase(PhaseEvent)
和afterPhase(PhaseEvent)
方法,无论是完整页面加载还是部分页面加载。
我在这里注意到这个错误:http://java.net/jira/browse/JAVASERVERFACES-1200,但它似乎已经修复了很久。
我在Java 6u33 x64上使用GlassFish 3.1.2.2。
答案 0 :(得分:1)
#{cc}
每次beforePhase()
实际需要执行afterPhase()
或<f:phaseListener>
UIViewRoot
方法时,都会重新评估#{cc}
。那时EL范围内没有binding
。它仅在组件范围内可用。
如果public MyComponent() {
FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put("ccc", this);
}
在复合组件的构造函数中指向至少一个请求作用域变量,它可以正常工作:
<f:phaseListener binding="#{ccc}" />
与
<f:phaseListener>
如果你有多个这种类型的复合组件,那么这个结构只会失败。
您最好寻找替代方法:完全摆脱public MyComponent() {
FacesContext.getCurrentInstance().getViewRoot().addPhaseListener(this);
}
并在复合组件的构造函数中使用UIViewRoot#addPhaseListener()
:
"javax.faces.NamingContainer"
无关,最好使用UINamingContainer.COMPONENT_FAMILY
常量而不是硬编码{{1}}。