为什么 <p:ajax> 侦听器在一个页面中使用时被多次调用,而该页面使用 <ui:include> 包含在另一个页面中

why <p:ajax> listener being called multiple times when it is used in a page which is included using <ui:include> in another page

我在将 <p:ajax .../> 放置在一个页面中时遇到了一个奇怪的问题,该页面包含在使用 ui:include 的另一个页面中。问题是 <p:ajax listener="someMethod"/>listener 在这种情况下被调用了不止一次!

例如,我创建了一个复合组件来呈现 list-of-value 组件。具体如下:

<?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.w3c.org/1999/xhtml"
      xmlns:p="http://primefaces.org/ui"
      xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface componentType="LovComponent">
    <composite:attribute name="actionListener" method-signature="void openModalDialog(java.lang.String)"/>
    <composite:attribute name="selectEventListener" method-signature="void selectAction(org.primefaces.event.SelectEvent)"/>
    <composite:attribute name="id"/>
    <composite:attribute name="update"/>
    <composite:attribute name="value"/>
    <composite:attribute name="style"/>
</composite:interface>
<composite:implementation>
        <p:inputText id="#{cc.attrs.id}" value="#{cc.attrs.value}" style="#{cc.attrs.style}"/>
        <p:commandButton immediate="true" process="@this"  icon="ui-icon-search" actionListener="#{cc.attrs.actionListener}">
            <p:ajax event="dialogReturn" listener="#{cc.selectEventListener}" update="#{cc.attrs.update}"/>
        </p:commandButton>
</composite:implementation>
</html>

它可以正常工作并呈现如下内容:

当用户单击该按钮时,它将在模式对话框中显示一个值列表。之后当用户 select 值之一时(He/She 应该点击那个愚蠢的刷新按钮!)

然后对话框关闭,在支持 bean 中调用 select 侦听器以在正确的 bean(数据持有者 bean)中设置值。

<p:cellEditor>
      <f:facet name="output">
            <p:outputLabel id="casProfileAllowedCurrInfoGbiCurrencyCodeOut" value="#{casProfileAllowedCurrInfo.gbiCurrency.code}"/>
      </f:facet>
      <f:facet name="input">
            <g:Lov id="casProfileAllowedCurrInfoGbiCurrencyCodeIn" selectEventListener="#{accountProfileController.allowedCurrenciesPageFragmentCasProfileAllowedCurrInfoSelectAction}"
                                value="#{casProfileAllowedCurrInfo.gbiCurrency.code}"
                                update=":profileDetailform:allowedCurrenciesCasProfileAllowedCurrInfoDataTable"
                                actionListener="#{accountProfileController.openModalDialog('CurrencyLov')}"
                                style="width:98%"/>
      </f:facet>
</p:cellEditor>

对话框中 select 按钮(带有刷新图标的按钮!)的代码:

<p:column headerText="#{label.SELECT}">
     <p:commandButton icon="ui-icon-refresh" actionListener="#{currencyLovController.closeDialog(gbiCurrency)}" />
</p:column>

在独立页面中使用此组合时,selectEventListener 的方法(LOV 组合的自定义属性)在用户的selection 完成后被调用一次。 (这是期望的行为)

现在我的问题是:

当我在使用 ui:include 包含在另一个页面中的页面中使用它时,侦听器被调用了两次!坏消息是第二次 selected 的值是 null!我找不到在包含页面中使用它之间的关系,但是,我以某种方式确定它有一个连接,因为当我将它包含在一个两级包含页面中时,它被调用了三次并且 select第二次和第三次ed值为null

如有任何帮助,我们将不胜感激。

[更新]

我将我的子系统打包为 weblogic shared-library 并且我有一个 MainWeb 应用程序,它作为应用程序部署在 weblogic 中。

我用Weblogic 12c,JSF2.2 apache my-faces 2.2.7,primefaces 5.1.

终于找到问题了!这不是因为将 composites 包含在彼此内部。 Weblogic 中的部署方式提出了问题。听起来可能有点奇怪,但当我停止使用 Weblogic Shared-Library 部署时,问题就消失了。

我设法将每个子系统部署为共享库,并将用于一般用途(用户身份验证、安全性、菜单、页面模板、导航等)的主项目部署为 Web 应用程序它依赖于共享库(打包的模块化部署)。

当出现上述问题时,我开始从共享库中删除配置文件(faces-config.xml、web.xml),但没有任何办法可以解决问题。

最后我改变了部署方式,暂时保留共享库部署。当我将整个应用程序打包为一个部署时,问题就消失了!

我找不到导致问题的原因,但现在至少可以正常工作了!

希望对其他人有所帮助。