【问题标题】:Override ui:insert and ui:include-Handler覆盖 ui:insert 和 ui:include-Handler
【发布时间】:2016-01-20 16:21:36
【问题描述】:

manyothertopics关于如何覆盖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> 之前进行挂钩,这样我就可以重用我即将开发的插件而不更改任何现有代码。

【问题讨论】:

  • "... 不更改任何现有代码":你不能。至少,并非没有与特定实现(Mojarra 或 MyFaces)紧密耦合。如果这不是问题,那么请告诉您希望获得哪个实现的答案。否则,回答者必须考虑所有实现特定的解决方案,这有点过火了。另一种选择是咬紧牙关,将所有<ui:include> 替换为<my:include>(但您已经知道了)。
  • 嗨 BalusC。很高兴知道,一个通用的解决方案是不可能的,所以我可以停止搜索它。我找到了this issue,我尝试做他想做的事情。但他的回答也没有得到满意的回答。当我使用 JSF 事件(PreRenderView 或 preRenderComponent)时,xhtml 文件已经包含在内 - 所以我丢失了这些信息。
  • 合理的要求。这可以做到,但不幸的是,解决方案将是特定于实现的,您只能将其绑定到 webapp(因此不能使其成为库的一部分)。因此,如果您说出您正在使用哪个实现,那么您就可以得出一个答案。
  • 谢谢!我正在使用 Mojarra 2.1.19。今天我还尝试自定义 ui:debug - 没有工作。我很震惊 JSF 规范没有提供足够的钩子来挂钩:(

标签: jsf jsf-2 facelets


【解决方案1】:

...无需更改任何现有代码

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

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

鉴于您希望达到与Customize ui:include rendering to add prefix/postfix<ui:include><ui:define> 中所要求的相同:

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

输入

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

输出

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

您可以通过编辑复制粘贴的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)includeDefinition(UIComponent, String) 扩展到第366 行,如下所示:

    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));
    }
    

在测试过程中,我发现了一个警告。我的 HTML &lt;title&gt; 模板如下:

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

因此,评论也会出现在 &lt;title&gt; 元素中。不幸的是,HTML 标题中的 cmets 是 invalid 语法(仅允许 PCDATA),它们被逐字解释,因此显示在文档标题中。您可能希望根据定义的nameparent 创建一个黑名单。

【讨论】:

  • 嗨fritjof,重定向到某些包含网址不是重点。这样做的原因是将所有includesinserts 包装到&lt;div data-file-url="/app/include_file.xhtml"&gt; 中(当然仅在调试模式下)。所以我可以将这些 div 加边框以查看网页的模板结构并且(这是最大的一点)我可以使用 IntelliJ 的“远程调用”插件直接从网络浏览器中打开 xhtml 片段。这听起来是不是很疯狂?
猜你喜欢
  • 2014-12-02
  • 1970-01-01
  • 2018-10-07
  • 2019-12-18
  • 2012-08-17
  • 2012-07-18
  • 2015-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多