自定义 ui:include 渲染以添加 prefix/postfix
Customize ui:include rendering to add prefix/postfix
我需要自定义 ui:include 渲染器,使其在生成 HTML 输出时还添加一条注释,说明包含文件的开始和结束。
例子,假设一个空白 file.xhtml
:
输入
<ui:include src="file.xhtml" />
输出
<!-- START file.xhtml -->
<!-- END file.xhtml -->
目前我正在将 JSF2.2 与 MyFaces 结合使用,您知道我该怎么做吗?
ui:include 不是 UiComponent
,也没有渲染器。它是一个 Facelet TagHandler
,因此在视图为 built(或恢复)时执行。您必须修改 TagHandler
以将带有所需注释的其他 ELInstruction
实例包含到组件树中。
我认为 JSF 没有提供任何好的扩展点来覆盖现有标记库的标记处理程序。您可以在自己的标签库中定义一个新标签。您可以尝试替换现有的标记库定义,但我不确定这对于 built-in 库是否可行。或者您可以通过为 class 提供您自己的定义来隐藏 class 路径中原始标记处理程序的 class 定义(您可以通过复制和修改原始源代码来获得) .所有这些方法都需要ui重复框架代码,因此维护起来很脆弱。
我建议定义以下 facelet 标签:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
>
<ui:composition>
<h:outputText value="<START FILE!--#{source}-->"/>
<ui:include src="#{source}">
<ui:insert name="includeParams"/>
</ui:include>
<h:outputText value="<!--END FILE!--#{source}-->"/>
</ui:composition>
</html>
并在代码中使用此标记代替 ui:include:
<my:include source="file.xhtml">
<ui:define name="includeParams">
<ui:param name="param1" value="value1"/>
<ui:param name="param2" value="value2"/>
</ui:define>
</my:include>
也可以通过 TagDecorator 元素进行自定义,但要实现您的目标需要一些努力。
但要注意: 只有在 <ui:include>
.
中没有 <ui:param>
的情况下,该解决方案才有效
以下四个 TODO 是必需的:
- 在您的 taglib.xml
中定义包装标签
<namespace>http://my-namespace.com/tags/my-tags</namespace>
<tag>
<tag-name>includeWithComment</tag-name>
<source>my/package/includeWithComment.xhtml</source>
<attribute>
<name>src</name>
</attribute>
</tag>
- 为包装器创建 xhtml includeWithComment.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition>
<!-- START ${src} -->
<ui:include src="${src}" />
<!-- END ${src} -->
</ui:composition>
</html>
- 在 web.xml 中定义您的 TagDecorator,如下所示:
<context-param>
<param-name>javax.faces.FACELETS_DECORATORS</param-name>
<param-value>my.package.CommentTagDecorator</param-value>
</context-param>
- 创建您的 TagDecorator 并为其注入活力。 (摘自this blogpost)
package my.package;
public class CommentTagDecorator implements TagDecorator {
@Override
public Tag decorate(Tag tag) {
if (!tag.getNamespace().equals("http://xmlns.jcp.org/jsf/facelets")
|| !tag.getLocalName().equals("include")
) {
return null;
}
return new Tag(tag.getLocation(), "http://my-namespace.com/tags/my-tags",
"includeWithComment", "t:includeWithComment", tag.getAttributes());
}
}
最后你的输出看起来像
<!-- START /include/popup.xhtml -->
[...]
<!-- END /include/popup.xhtml -->
我需要自定义 ui:include 渲染器,使其在生成 HTML 输出时还添加一条注释,说明包含文件的开始和结束。
例子,假设一个空白 file.xhtml
:
输入
<ui:include src="file.xhtml" />
输出
<!-- START file.xhtml -->
<!-- END file.xhtml -->
目前我正在将 JSF2.2 与 MyFaces 结合使用,您知道我该怎么做吗?
ui:include 不是 UiComponent
,也没有渲染器。它是一个 Facelet TagHandler
,因此在视图为 built(或恢复)时执行。您必须修改 TagHandler
以将带有所需注释的其他 ELInstruction
实例包含到组件树中。
我认为 JSF 没有提供任何好的扩展点来覆盖现有标记库的标记处理程序。您可以在自己的标签库中定义一个新标签。您可以尝试替换现有的标记库定义,但我不确定这对于 built-in 库是否可行。或者您可以通过为 class 提供您自己的定义来隐藏 class 路径中原始标记处理程序的 class 定义(您可以通过复制和修改原始源代码来获得) .所有这些方法都需要ui重复框架代码,因此维护起来很脆弱。
我建议定义以下 facelet 标签:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
>
<ui:composition>
<h:outputText value="<START FILE!--#{source}-->"/>
<ui:include src="#{source}">
<ui:insert name="includeParams"/>
</ui:include>
<h:outputText value="<!--END FILE!--#{source}-->"/>
</ui:composition>
</html>
并在代码中使用此标记代替 ui:include:
<my:include source="file.xhtml">
<ui:define name="includeParams">
<ui:param name="param1" value="value1"/>
<ui:param name="param2" value="value2"/>
</ui:define>
</my:include>
也可以通过 TagDecorator 元素进行自定义,但要实现您的目标需要一些努力。
但要注意: 只有在 <ui:include>
.
<ui:param>
的情况下,该解决方案才有效
以下四个 TODO 是必需的:
- 在您的 taglib.xml 中定义包装标签
<namespace>http://my-namespace.com/tags/my-tags</namespace>
<tag>
<tag-name>includeWithComment</tag-name>
<source>my/package/includeWithComment.xhtml</source>
<attribute>
<name>src</name>
</attribute>
</tag>
- 为包装器创建 xhtml includeWithComment.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:composition>
<!-- START ${src} -->
<ui:include src="${src}" />
<!-- END ${src} -->
</ui:composition>
</html>
- 在 web.xml 中定义您的 TagDecorator,如下所示:
<context-param>
<param-name>javax.faces.FACELETS_DECORATORS</param-name>
<param-value>my.package.CommentTagDecorator</param-value>
</context-param>
- 创建您的 TagDecorator 并为其注入活力。 (摘自this blogpost)
package my.package;
public class CommentTagDecorator implements TagDecorator {
@Override
public Tag decorate(Tag tag) {
if (!tag.getNamespace().equals("http://xmlns.jcp.org/jsf/facelets")
|| !tag.getLocalName().equals("include")
) {
return null;
}
return new Tag(tag.getLocation(), "http://my-namespace.com/tags/my-tags",
"includeWithComment", "t:includeWithComment", tag.getAttributes());
}
}
最后你的输出看起来像
<!-- START /include/popup.xhtml -->
[...]
<!-- END /include/popup.xhtml -->