在页面上执行任何其他操作之前,我有一个共同的任务是选择一个或多个“LocalizacaoTO”。
目前,数据检索/处理/ajax 事件等的逻辑是在一个ViewScoped
名为“SeletorLocalizacaoMB”的 bean 上维护的,我想在同一页面上使用同一个 bean 的多个实例。
首先我使用复合组件,但是当我选择一个节点时,它存储在页面上的最后一个 bean 上。
如果我在 TesteSeletorMB 上声明了 3 个实例:
@Named
@ViewScoped
public class TesteSeletorMB implements Serializable {
@Inject
@Getter @Setter
private SeletorLocalizacaoMB instanceOne;
@Inject
@Getter @Setter
private SeletorLocalizacaoMB instanceTwo;
@Inject
@Getter @Setter
private SeletorLocalizacaoMB instanceThree;
}
无论我使用页面上的哪个组件,instanceThree 始终保存值。
根据一些研究,我了解到复合组件不是解决此问题的理想解决方案。
所以我更改了 UI 实现并使用 Facelets 创建了一个名为 seletor.xhtml 的“模板”。
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui">
<p:dialog header="Busca Hierarquica"
id="#{id}ModalTree"
widgetVar="dlgSelecaoHierarquica"
showEffect="fade"
hideEffect="fade"
closeOnEscape="true"
modal="#{bloqueiaModal}"
height="400px"
width="500px">
<h:panelGrid columns="2">
<p:commandButton id="#{id}btnSelecao"
value="Selecionar e Voltar"
action="#{mb['selecionarLocalHierarquico']}"
update="@(.#{id}-auto-complete)"
oncomplete="bloqueiaAutoMulti();"/>
<p:commandButton value="Voltar"
type="button"
onclick="PF('dlgSelecaoHierarquica').hide();" />
</h:panelGrid>
<p:scrollPanel style="width:100%;height:350;" mode="native">
<p:tree id="#{id}Tree"
style="width:100%;height:100%;"
styleClass="estilo-arvore"
value="#{mb.arvoreHierarquica}"
var="local"
selectionMode="multiple"
dynamic="true"
animate="true">
<p:ajax event="select" listener="#{mb['onNodeSelect']}" update="@this"/>
<p:treeNode >
<h:outputText value="#{local.cdClasseLocal}: #{local.cdLocalizacao} #{local.niveis}" />
</p:treeNode>
</p:tree>
</p:scrollPanel>
</p:dialog>
</ui:composition>
测试页面使用<ui:include>
<f:subview id="seletorAlpha">
<ui:include src="/template/seletor.xhtml">
<ui:param name="mb" value="#{testeSeletorMB.seletorAlpha}" />
<ui:param name="id" value="alpha" />
</ui:include>
</f:subview>
<f:subview id="seletorBravo">
<ui:include src="/template/seletor.xhtml">
<ui:param name="mb" value="#{testeSeletorMB.seletorBravo}" />
<ui:param name="id" value="bravo" />
</ui:include>
</f:subview>
测试 Bean 持有多个实例:
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
@Named
@ViewScoped
public class TesteSeletorMB implements Serializable {
@Inject
@Getter @Setter
private SeletorLocalizacaoMB seletorAlpha;
@Inject
@Getter @Setter
private SeletorLocalizacaoMB seletorBravo;
}
'seletor.xhtml' 上使用的 CDI Bean
import javax.inject.Named;
import org.omnifaces.cdi.ViewScoped;
@Named
@ViewScoped
public class SeletorLocalizacaoMB implements Serializable {
private List<LocalizacaoTO> locaisHierarquicosSelecionados;
private TreeNode arvoreHierarquica;
//PostConstruct, Ajax events and things :)
}
在我的示例中,我希望 TesteSeletorMB 变量(seletorAlpha 和seletorBravo)在它们的列表中保持不同的值。可能吗?
我试图将 SeletorLocalizacaoMB 范围更改为@Dependent
但它也没有工作。这就是事情变得混乱的地方。阅读CDI API,第一个状态说:
使用范围 @Dependent 声明的 bean 与具有其他 >built-in 范围类型的 bean 的行为不同。当一个 bean 被声明为具有@Dependent 范围时:
多个注入点之间不会共享任何注入的 bean 实例。
它不应该拥有相同的实例,对吧?!
环境
- WebSphere 应用服务器 8.5.5.2
- Apache MyFaces 2.0.2
- PrimeFaces 5.0
- OmniFaces 1.7
如有必要,我可以提供额外的数据。我没有粘贴所有的“SeletorLocalizacaoMB”代码,因为它有很多依赖项,我觉得问题与类如何处理操作无关。