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

Tuu*_*nen 5 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");
    }

}
Run Code Online (Sandbox Code Playgroud)

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

将它添加到其他 UIComponents 中没有区别,只有复合组件包装器似乎会改变行为。

找不到信息为什么会这样?规范的链接?

小智 5

在这种情况下,规范真的很混乱,指出:“这些方法在请求处理生命周期的渲染响应阶段被调用。encodeAll() 将导致这个组件及其所有从 isRendered() 返回 true 的子组件和构面渲染,不管 getRendersChildren() 返回值的值。encodeBegin()、encodeChildren() 和 encodeEnd() 有责任为这个组件的开始创建响应数据,这个组件的子组件(仅当 rendersChildren此组件的属性为真),以及此组件的结尾。”

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

我尝试了以下方法:

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

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

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

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

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

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

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

我希望这至少对您有价值,不幸的是我无法提供更彻底的答案。:( 似乎也没有其他人知道这一点。