JSF 2.0:何时调用encodeAll以及何时调用encodeBegin?

2024-03-07

考虑一个自定义 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()方法被调用。

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

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


在这种情况下,规范确实很混乱,指出: “这些方法在请求处理生命周期的渲染响应阶段被调用。encodeAll() 将 导致该组件及其所有从 isRendered() 返回 true 的子组件和构面被渲染,无论 getRendersChildren() 返回值的值。编码开始(),编码儿童(),和 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 的类中) 调用找到的相应方法。

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

B)包装组件(抄送:实现..等)

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JSF 2.0:何时调用encodeAll以及何时调用encodeBegin? 的相关文章