【发布时间】:2013-10-30 13:26:00
【问题描述】:
我正在开发一个由 core 组件组成的 JSF 2 应用程序,该组件可以通过(通常是客户端特定的)代码扩展。一般来说:应用程序的扩展部分先于核心部分。
对于 Java 代码,这是通过使用常规机制完成的。对于表示层,我们使用javax.faces.view.facelets.ResourceResolver 实现,它首先尝试在 extension jar 中查找资源,然后再使用 core 资源。
我们使用大量复合组件来实现可重用标记。想想显示地址、薪水等的组件。
当涉及到应用程序的可扩展特性时,Facelets 引起了很大的麻烦,我开始怀疑是否有解决我们遇到的问题的方法。
我们想要实现的是为复合组件提供一个标准接口,但通过解决多个实现以某种方式覆盖实现,其中扩展了 实施应先于核心实施。
这个想法当然是,core 定义应用程序的标准布局/模板,extensions 定义客户端特定的格式选项,或隐藏/显示部分应用程序执行的托管模型。
例如:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:pui="http://java.sun.com/jsf/composite/pui">
<cc:interface>
<cc:attribute name="saveButtonLabel" />
<cc:attribute name="saveButtonIcon" />
<cc:attribute name="saveButtonIconPosition" />
</cc:interface>
<cc:implementation>
<pui:pension_plan_custom_state pensionPlanBean="#{pensionPlanBean}" />
<pui:pension_plan_general pensionPlanBean="#{pensionPlanBean}" />
<pui:pension_plan_pension_plan pensionPlanBean="#{pensionPlanBean}" />
<pui:pension_plan_salary pensionPlanBean="#{pensionPlanBean}" />
<pui:pension_plan_investments pensionPlanBean="#{pensionPlanBean}" />
<pui:pension_plan_benefit_types benefitTypes="#{pensionPlanBean.benefitTypesViewData}" />
<div class="buttons">
<!-- Irrelevant -->
</div>
</cc:implementation>
</ui:composition>
以pension_plan_benefit_types 复合组件为例。它的接口规定了名称为benefitTypes 的属性将由客户端提供。如果客户只希望屏幕的这一部分被不同的内容覆盖,而不是标准实现,我们需要一个地方来覆盖它。
还要注意,core 不知道(可选)extension 提供的命名空间。 core 并不关心,只要复合的接口是稳定的并且不需要更改即可。
作为最后的手段,已尝试以下方法(伪代码):
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:pui="http://java.sun.com/jsf/composite/pui">
<cc:interface>
<cc:attribute name="benefitTypes" required="true" type="com.foo.bar.PensionPlanBenefitTypesViewData" />
</cc:interface>
<cc:implementation>
<ui:include src="/resources/pui/markup/pension_plan_benefit_types_markup.xhtml" />
</cc:implementation>
</ui:composition>
这个想法在哪里,javax.faces.view.facelets.ResourceResolver 会来拯救我们。
它“有点工作”,但是根据我们必须为复合组件编写的实现,我们会在臭名昭著的构建中遇到各种问题 - 与 JSF 生命周期的渲染时间部门相比。它基本上不像我们期望的那样工作。
现在最大的问题是:
有没有一种方法可以让我们既拥有稳定的合约/命名空间,又拥有多个动态解析的实现?
希望有人能对此有所了解,感谢您的意见。
亲切的问候,
伦斯
【问题讨论】:
标签: jsf-2 facelets composite-component