如何在 JSF 中正确使用组件绑定? (会话范围 bean 中的请求范围组件)
Posted
技术标签:
【中文标题】如何在 JSF 中正确使用组件绑定? (会话范围 bean 中的请求范围组件)【英文标题】:How to use component binding in JSF right ? (request-scoped component in session scoped bean) 【发布时间】:2013-09-11 03:40:36 【问题描述】:Mojara 2.1.21
我已经根据 cmets 更新了我的问题。我有两种情况,组件绑定到服务器会话 bean。 (其他信息链接:Binding attribute causes duplicate component ID found in the view 和 https://***.com/a/12512672/2692917)
版本 1:
single.xhtml:
<h:outputText value=... binding="#mysessionbean.out" />
java:
@SessionScoped @Named public class Mysessionbean
UIOutput out;
//getter and setter ....
版本 2:
模板.xhtml:
<h:outputText value=... binding="#mysessionbean.out"
view1.xhtml:
<ui:composition template="template.xhtml" />
view2.xhtml:
<ui:composition template="template.xhtml" />
java:
@SessionScoped @Named public class Mysessionbean
UIOutput out;
//getter and setter ....
版本 1 没问题。 (至少到目前为止我还没有遇到任何错误)。但是在版本 2 中,如果我从一个页面导航到另一个页面,则会发生重复的 id 错误。为什么会这样? 将(请求范围的)组件(在版本 1 中)与会话范围的绑定一起使用是否安全? 还有其他用例需要考虑吗?
编辑: 功能要求1:
我想在视图中使用 Primefaces 数据表。我需要这个数据表中的一些信息。 (如选中的行或行索引)。所以绑定数据表可以帮助我检索这些信息。
功能要求2:
复合组件中的组件绑定。它们将绑定到会话范围的 bean。 (而且主要用在一个页面上,但是如果我在另一个页面上使用呢?
要求 3
“版本2”中的情况。带有 primefaces 菜单和会话范围绑定的模板。为此,我使用了 EL-Binding。
【问题讨论】:
这绝对是不对的,不。组件实例本质上是请求范围的。另请参阅:***.com/questions/2101755。在发布答案之前,请详细说明您认为这是正确解决方案的具体功能要求。然后我可以说出正确的方法。 @BalusC 感谢您的评论!我已经更新了我的问题。 您还没有详细说明功能需求。 @BalusC 我已经更新了我的问题 2 和 3 不清楚。缺少功能需求。 【参考方案1】:在 JSF 2.x 中,除非您想以编程方式操作组件(这本身也很可疑),否则没有明智的现实世界用例将组件绑定到支持 bean。如果它们进一步没有在 backing bean 本身中使用,或者仅仅是它们的属性被扁平化,那么肯定不会。
关于获取数据表当前行的功能需求,这里列出了很多更好的方法,How can I pass selected row to commandLink inside dataTable?,例如如果你的环境支持EL 2.2:
<h:dataTable value="#bean.items" var="item">
<h:column>
<h:commandLink value="Foo" action="#bean.foo(item)" />
最后两个要求完全不清楚。至少,如果你正在做类似的事情:
<x:someComponent binding="#bean.someComponent" />
在 bean 中
someComponent.setSomeAttribute(someAttribute);
someComponent.setOtherAttribute(otherAttribute);
那么你应该这样做
<x:someComponent someAttribute="#bean.someAttribute" otherAttribute="#bean.otherAttribute" />
或者,如果您打算像这样在视图中的其他位置使用该组件
<h:inputText ... required="#not empty param[bean.save.clientId]" />
...
<h:commandButton binding="#bean.save" ... />
并且该实例在 bean 中进一步没有被使用,然后完全摆脱不必要的属性:
<h:inputText ... required="#not empty param[save.clientId]" />
...
<h:commandButton binding="#save" ... />
如果由于某种不清楚的原因真的真的没有办法,那么将会话范围 bean 的所有请求范围属性拆分为一个单独的请求范围 bean,然后您将其绑定到表单操作。会话范围的一个可以作为请求范围的一个@ManagedProperty
注入。
另见:
Binding attribute causes duplicate component ID found in the view How does the 'binding' attribute work in JSF? When and how should it be used?【讨论】:
很好的抽象解释!对于您的最后一个建议,我正在使用 CDI,那么我可以在会话范围内注入请求范围的包装类吗?因为可能我需要会话范围 bean 中的组件,因为相反。 是的,反过来也可以。【参考方案2】:我们遇到了类似的问题,我只想分享我们的解决方案:
问题: 在一个视图中,有一个(扩展的大部分定制的)数据表。
<x:dataTable binding="#bean.someSomeDataTable" />
在导航到另一个页面并返回后,我们希望数据表具有完全相同的状态。以前我们通过将数据表绑定到支持 bean 来解决这个问题。这适用于 JSP。使用 Facelets,我们无法做到这一点(重复 ID 错误)。所以我们使用了绑定,但只是保存/恢复了数据表组件的状态。
public HtmlDataTable getSomeDataTable()
HtmlDataTable htmlDataTable = new HtmlDataTable();
if (tableState != null)
htmlDataTable.restoreState(FacesContext.getCurrentInstance(), tableState);
return htmlDataTable;
public void setSomeDataTable(HtmlDataTable table)
tableState = table.saveState(FacesContext.getCurrentInstance());
【讨论】:
感谢您分享您的解决方案!以上是关于如何在 JSF 中正确使用组件绑定? (会话范围 bean 中的请求范围组件)的主要内容,如果未能解决你的问题,请参考以下文章
使用具有绑定和会话范围的数据表时,已在视图中找到组件 ID [重复]
是否在会话范围的 JSF 支持 bean 中观察到 CDI 事件
如何(以及何时?)在 JSF 2.0 中删除 Session 范围的 bean