【问题标题】:How can I access the content of something created with <ui:define> programmatically?如何以编程方式访问使用 <ui:define> 创建的内容?
【发布时间】:2015-06-07 06:22:01
【问题描述】:

在上下文中,我可以在哪里找到使用 &lt;ui:define&gt; 构建的东西的信息?我想访问在我的 bean 中使用 &lt;ui:define name="title"&gt;Some title&lt;/ui:define&gt; 定义的页面标题。

为了说明我的问题,我可以访问使用定义的变量

<ui:param name="myVariable" value="This is my variable!"/>

通过查看 EL 上下文中的变量映射器,像这样

VariableMapper variableMapper = elContext.getVariableMapper();
String myVariable = variableMapper.resolveVariable("myVariable").getValue(elContext).toString();

这适用于&lt;ui:param&gt;,但如何处理&lt;ui:define&gt;

【问题讨论】:

  • 你到底想用它做什么?它基本上代表一个部分 JSF 组件树,而不一定是像 ui:param 这样的普通字符串。
  • @BalusC:我只是想检查一下,是否已经定义了名为 title 的东西,如果没有,请设置一个通用页面标题。我很好奇,如何以编程方式完成。我在上下文中搜索带有键 title 的组件树,但找不到它。
  • 好的,你基本上是想检查是否在模板客户端中定义了&lt;ui:define name="title"&gt;&lt;ui:insert name="title"&gt;,不管内容如何? IE。您只对基于您可以在模板中其他地方使用的布尔值truefalse 感兴趣?如果是这样,那么这是否可以接受为欺骗? stackoverflow.com/questions/26070704/…
  • @BalusC:页面标题应采用以下形式:AppName - PageTitle。有些页面没有定义PageTitle,它们将AppName 作为通用标题。有些人这样做,对于这些页面,定义的PageTitle 应与AppNamedash 前缀连接。在处理这个问题时,我尝试在 bean 中检索 ui:define 的内容,以查看此信息在上下文中的存储方式和位置,但无法找到它。我花了几个小时试图解决这个问题,但我在网上找不到任何相关信息。任何正确方向的提示也非常受欢迎。
  • @BalusC:您提供的链接绝对是这个问题的可接受解决方案,但我有兴趣学习如何通过代码访问 ui:define 块。

标签: jsf facelets


【解决方案1】:

这是通过标准 API 无法实现的。 Xtreme Biker 发布了一个绝妙的技巧,其中在 &lt;ui:insert&gt; 中指定了“默认”&lt;ui:param&gt; 值,当 &lt;ui:define&gt; 实际上被指定为Test if ui:insert has been defined in the template client 上的答案时,该值将被覆盖(因此不存在)

一个(hacky)替代方法是为该作业创建一个自定义标记处理程序。 &lt;ui:define&gt;s 按其名称收集在 &lt;ui:composition&gt; 后面的 CompositionHandler taghandler 类的 Map handlers 字段中。这是(不幸的是)特定于实现的,MojarraMyFaces 有自己的实现,Mojarra 将字段命名为 handlers 和 MyFaces _handlers

由于该字段只是protected,最简单的方法是扩展CompositionHandler taghandler 类并至少公开apply() 方法中的键集作为FaceletContext 的属性。然而,由于CompositionHandler 类本身被声明为final,我们不能对其进行子类化。因此,无论如何我们都不能将其包装为委托并使用一些反射黑客来获取该字段。

这是一个基于 Mojarra 的启动示例,它将所有声明的 &lt;ui:define&gt; 处理程序名称收集在 Map&lt;String, Boolean&gt; 中,以便您可以在 EL 中很好地使用它们,例如 #{defined.foo ? '...' : '...'}#{not defined.foo ? '...' : '...'}

public class DefineAwareCompositionHandler extends TagHandlerImpl implements TemplateClient {

    private CompositionHandler delegate;
    private Map<String, Boolean> defined;

    @SuppressWarnings("unchecked")
    public DefineAwareCompositionHandler(TagConfig config) {
        super(config);
        delegate = new CompositionHandler(config);

        try {
            Field field = delegate.getClass().getDeclaredField("handlers");
            field.setAccessible(true);
            Map<String, DefineHandler> handlers = (Map<String, DefineHandler>) field.get(delegate);

            if (handlers != null) {
                defined = new HashMap<>();

                for (String name : handlers.keySet()) {
                    defined.put(name, true);
                }
            }
        }
        catch (Exception e) {
            throw new FaceletException(e);
        }
    }

    @Override
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
        ctx.setAttribute("defined", defined);
        delegate.apply(ctx, parent);
    }

    @Override
    public boolean apply(FaceletContext ctx, UIComponent parent, String name) throws IOException {
        return delegate.apply(ctx, parent, name);
    }

}

在您的自定义my.taglib.xml中注册如下:

<tag>
    <tag-name>composition</tag-name>
    <handler-class>com.example.DefineAwareCompositionHandler</handler-class>
</tag>

你可以如下使用它:

<my:composition
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://xmlns.jcp.org/jsf/core"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
    xmlns:my="http://example.com/ui"
>
    <ui:insert name="foo">
        ...
    </ui:insert>

    <div class="#{defined.foo ? 'style1' : 'style2'}">
        ...
    </div>
</my:composition>

再一次,这是 hacky(因为它是特定于实现的),我不建议使用它。

另见:

【讨论】:

  • 我现在明白为什么我不能这么容易地找到这方面的信息了。非常感谢您提供如此多的见解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 2020-11-14
  • 1970-01-01
  • 1970-01-01
  • 2017-11-07
相关资源
最近更新 更多