我正在开发一个 JSF 2 应用程序,该应用程序由一个可以通过(通常是客户端特定的)代码扩展的核心组件组成。一般来说:应用程序的扩展部分先于核心部分。
对于 Java 代码,这是通过使用常规机制来完成的。对于表示层,我们使用一种javax.faces.view.facelets.ResourceResolver
实现,它首先尝试在扩展jar 中查找资源,然后再使用核心资源。
我们使用很多复合组件来进行可重用标记。想想显示地址、薪水等的组件。
当谈到应用程序的可扩展性时,Facelets 引起了很大的麻烦,我开始怀疑是否有解决我们遇到的问题的方法。
我们想要实现的是为复合组件提供标准接口,但通过解决多个实现以某种方式覆盖实现,其中扩展实现应该先于核心实现。
当然,核心定义了应用程序的标准布局/模板,扩展定义了特定于客户端的格式化选项,或者隐藏/显示应用程序执行的托管模型的一部分。
例如:
<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
客户端给出。如果客户希望屏幕的这一部分被不同的内容覆盖,而不是标准实现,我们需要一个地方在某个地方覆盖它。
另请注意,核心不知道(可选)扩展提供的命名空间。核心并不关心,只要复合的接口稳定且不需要更改即可。
作为最后的手段,已尝试以下方法(伪代码):
<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 生命周期的渲染时间部门相比。它基本上不像我们期望的那样工作。
现在最大的问题是:
有没有一种方法可以让我们既拥有稳定的合约/命名空间又拥有多个动态解析的实现?
希望有人能对此有所了解,感谢您的投入。
亲切的问候,
任斯