JSF 2.0:什么时候调用encodeAll,何时调用encodeBegin?

时间:2010-11-26 09:35:44

标签: jsf jsf-2

考虑自定义UIComponent(仅用于测试目的):

public class UITest extends UIComponentBase {

    @Override
    public void encodeBegin(FacesContext context) throws IOException {
        System.out.println("encodeBegin");
    }

    @Override
    public void encodeAll(FacesContext context) throws IOException {
        System.out.println("encodeAll");
    }

}

当我将它添加到复合组件内的页面时,会调用encodeBegin()方法。但是,将其添加到复合组件外部的页面时,将调用encodeAll()方法。

在其他UIComponents中添加它没有任何区别,只有复合组件包装似乎改变了行为。

无法找到信息为何如此?指向规范的链接?

1 个答案:

答案 0 :(得分:4)

在这种情况下,规范非常混乱,说明: “这些方法在请求处理生命周期的渲染响应阶段调用.codesAll()将 无论如何,使得此组件及其所有子组件和facet都从isRendered()返回true getRendersChildren()返回值的值。 encodeBegin(),encodeChildren()和 encodeEnd()负责为此组件的开头创建响应数据 组件的子节点(仅在此组件的rendersChildren属性为true时调用),以及结尾 这个组件分别是。“

然而,这似乎是新功能和旧功能的混合,其中新功能(encodeAll)在某些方面似乎不完整:

我尝试了以下内容:

A)直接在页面中调用组件(无包装器)

  1. 扩展UIComponentBase(或其他UIComponent类,如UIInput,UIOutput等),将其声明为标记,并在UI中使用它。 在这种情况下,如果不存在(覆盖),则调用encodeAll方法,如果不存在,则调用encodeBegin和encodeEnd方法!!

  2. 需要注意的另一件事是,您可以为组件创建自定义渲染器,这样您就可以将渲染逻辑与行为分开。 (通过创建另一个扩展Renderer的类,并使用@FacesRenderer对其进行注释) 这是它变得有趣的地方; Renderer只定义encodeBegin,encodeChildren和encodeEnd(没有提到encodeAll)。 现在逻辑似乎大致如下: if(encodeAll存在) 调用encodeAll(并忽略渲染器!) else if(encodeBegin,Children或end中的任何一个存在于扩展UIComponent的类中) 调用在该组件中找到的方法 else if(encodeBegin,children或end存在于扩展Renderer的类中) 调用找到的相应方法。

  3. 所以这意味着在扩展UIComponent的类中实现encodeAll(或encodeBegin ...等)会导致渲染器被忽略!

    B)包装组件(cc:implementation .. etc)

    在这种情况下,同样的事情发生在上面,除了在任何情况下都没有调用encodeAll,无论我做了什么。

    结论: 似乎encodeAll是实现渲染代码的某种新功能(或快捷方式),并且在这种情况下cc:implementation似乎有一个错误(它不会寻找encodeAll)。

    我希望这至少对你有一些价值,遗憾的是我无法提供更全面的答案。 :( 似乎没有其他人知道这一点。