如何在 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

JSF组件的动态值绑定

JSF 2.0 在整个会话中从浏览器和以编程方式设置区域设置 [重复]

在 Web 过滤器中访问会话范围的 JSF 托管 bean