覆盖ui:insert和ui:include-Handler

时间:2015-10-21 15:24:04

标签: jsf jsf-2 facelets

many other topics关于如何覆盖JSF中的现有渲染器。所有这些都导致faces-config中的相同条目。您“仅”需要component-familyrenderer-typerender-kit-id以及renderer-class

中的实施

我理解并可以重现所有这些示例,但在我的具体情况下,我想要覆盖<ui:include><ui:insert>的行为。遗憾的是,我无法找到,我必须在上述属性中添加哪些值,因为文件ui:taglib.xml并不像其他标记库那样冗长。

你有什么想法,如何覆盖它们?

修改:BalusC提及another topic,它使用<my:include><my:insert>等自定义标签,但我不想使用这些标签。如果我这样做,我必须重构我现有的所有代码,如果不使用我的自定义taglib,我的未来代码将无法正常工作。

我想在呈现<ui:include><ui:insert>之前挂钩,这样我就可以重用我即将开发的插件,而不用更改任何现有代码。

1 个答案:

答案 0 :(得分:3)

  

...而不更改任何现有代码

你不能。至少,并非没有紧密耦合到特定的实现(Mojarra或MyFaces)。另一种方法是咬住子弹并将所有<ui:include><ui:define>替换为<my:include><my:define>。 Facelets尚未完全抽象/标准化为JSF规范。只有Facelet cache factory,但没有Facelet上下文工厂,否则它很容易。通常,忘记以抽象方式自定义<ui:xxx>标记。您需要破解实施。

鉴于您正在使用Mojarra 2.1.19,您需要copypaste将其com.sun.faces.facelets.impl.DefaultFaceletContext类添加到您的Web应用程序项目中,并维护其com.sun.faces.facelets.impl包。 WAR中的类具有比WAR /WEB-INF/lib和服务器/lib中更高的类加载优先级。因此,将使用WAR中的这个。

鉴于您希望与<ui:include><ui:define>上的Customize ui:include rendering to add prefix/postfix中的问题相同:

  

示例,假设一个空白的文件.xhtml:

     

输入

<ui:include src="file.xhtml" />
     

输出

<!-- START file.xhtml -->
<!-- END file.xhtml -->

以下是如何通过编辑copypasted DefaultFaceletContext类来实现它:

  1. 在类中添加一个辅助方法,该方法创建一个注释组件(它只是一个普通的输出文本组件)。

    private static UIComponent createComment(String comment) {
        UIOutput text = new UIOutput();
        text.setValue("\n<!-- " + comment + " -->\n");
        return text;
    }
    
  2. 在第199行扩展oneliner方法includeFacelet(UIComponent, String),如下所示:

    parent.getChildren().add(createComment("START INCLUDE " + relativePath));
    facelet.include(this, parent, relativePath);
    parent.getChildren().add(createComment("END INCLUDE " + relativePath));
    
  3. 使用client.apply(this, parent, name)扩展第366行的includeDefinition(UIComponent, String),如下所示:

    int start = parent.getChildCount();
    found = client.apply(this, parent, name);
    
    if (found) {
        parent.getChildren().add(start, createComment("START DEFINE " + name));
        parent.getChildren().add(createComment("END DEFINE " + name));
    }
    
  4. 在测试期间,我发现了一个警告。我的HTML <title>模板如下:

    <h:head>
        <title><ui:insert name="title">#{view.viewId}</ui:insert></title>
    </h:head>
    

    因此,注释也会在<title>元素内部结束。不幸的是,HTML标题中的注释是invalid语法(仅允许PCDATA),它们按字面解释,因此显示在文档标题中。您可能希望根据定义的nameparent创建黑名单。