当前位置: 首页 > 知识库问答 >
问题:

在JSF中,'binding'属性是如何工作的?何时使用,如何使用?

弓磊
2023-03-14

在JSF中有很多关于属性和绑定属性的区分材料。

我对这两种方法的不同感兴趣。给定:

public class User {
    private String name;
    private UICommand link;

    // Getters and setters omitted.
}
<h:form>
    <h:commandLink binding="#{user.link}" value="#{user.name}" />
</h:form>

当指定value属性时,会发生什么非常简单。getter运行以返回Userbean的name属性值。该值被打印到HTML输出中。

<form action="/TestJSF/main.jsf" enctype="application/x-www-form-urlencoded"
    id="j_id_jsp_1847466274_1" method="post"  name="j_id_jsp_1847466274_1">
    <input name="j_id_jsp_1847466274_1" type="hidden" value="j_id_jsp_1847466274_1">
    <a href="#" onclick="...">Name</a>
    <input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState"
        type="hidden" value="-908991273579182886:-7278326187282654551">
</form>

绑定存储在哪里?

共有1个答案

杜正奇
2023-03-14

当构建/还原JSF视图(Facelets/JSP文件)时,将生成一个JSF组件树。此时,视图构建时,所有binding属性都将被评估(以及idattribtues和像JSTL这样的taghandlers)。当JSF组件需要在添加到组件树之前创建时,JSF将检查binding属性是否返回预创建的组件(即非null),如果是,则使用它。如果它不是预先创建的,那么JSF将“以通常的方式”自动创建组件,并以自动创建的组件实例作为参数调用binding属性后面的setter。

实际上,它将组件树中组件实例的引用绑定到限定范围的变量。在生成的组件本身的HTML表示中,这些信息是不可见的。无论如何,这些信息与生成的HTML输出无关。当表单提交并恢复视图时,JSF组件树将从头重新构建,所有binding属性将被重新计算,如上一段所述。在重新创建组件树之后,JSF将把JSF视图状态恢复到组件树中。

要知道和理解的重要一点是,具体的组件实例有效地限定了请求范围。它们是在每个请求上新创建的,在恢复视图阶段,它们的属性用来自JSF视图状态的值填充。因此,如果将组件绑定到支持bean的属性,则支持bean的范围绝对不应大于请求范围。另请参见JSF 2.0专门化第3.1.5章:

...

组件绑定通常与通过托管Bean创建工具动态实例化的JavaBeans一起使用(请参见第5.8.1节“VariableResolver和默认的VariableResolver”)。强烈建议应用程序开发人员将组件绑定表达式指向的托管bean放置在“request”范围内。这是因为将它放在会话或应用程序范围中需要线程安全,因为UIComponent实例依赖于在单个线程中运行。将组件绑定放置在“会话”范围内也可能对内存管理产生负面影响。

否则,组件实例将在多个请求中共享,这可能导致“重复组件ID”错误和“奇怪”行为,因为视图中声明的验证器、转换器和侦听器是从以前的请求中重新附加到现有组件实例的。症状很明显:它们被执行多次,每个请求在组件绑定到的相同范围内执行一次。

而且,在负载较重的情况下(即当多个不同的HTTP请求(线程)同时访问和操作同一个组件实例时),您可能迟早会面临应用程序崩溃,例如,UIComponent.popComponentFromel中的线程被卡住,或者使用richfaces UIDataAdaptorBase及其内部HashMap使用100%CPU的Java线程,甚至一些“奇怪的”IndexoutOfboundsExceptionConcurrentModificationException直接来自JSF实现源代码,而JSF正忙于保存或恢复视图状态(即堆栈跟踪指示

无论如何,以这种方式使用绑定,将整个组件实例绑定到bean属性,即使是在请求作用域bean上,在JSF2.x中也是相当罕见的用例,通常不是最佳实践。它预示着一种设计气味。您通常在视图端声明组件,并将它们的运行时属性(如value,以及styleclassdisabledrendered等)绑定到普通bean属性。然后,只需操作所需的bean属性,而不是抓取整个组件并调用与该属性关联的setter方法。

在需要基于静态模型“动态构建”组件的情况下,最好使用视图构建时标记,如JSTL(必要时在标记文件中),而不是createComponent()new SomeComponent()getchildrem().add()等等。另请参见如何将旧JSP的代码片段重构为某些等效的JSF?

或者,如果组件需要基于动态模型“动态呈现”,那么只需使用迭代器组件( 等)。另请参见如何动态添加JSF组件。

复合组件是完全不同的情况。将 中的组件绑定到支持组件(即由 标识的组件)是完全合法的。另请参见a.O.用f:convertdateTime将java.util.date拆分到表示小时和分钟的两个h:inputtext字段,以及如何用JSF2.0复合组件实现动态列表?

然而,有时您希望从特定组件内部了解不同组件的状态,这在与操作/值相关的验证相关的用例中更为常见。为此,可以使用binding属性,但不能与bean属性结合使用。您只需在binding属性中指定本地EL作用域中的唯一变量名,类似于sobinding=“#{foo}”,并且该组件在呈现响应期间直接位于#{foo}可用的UIComponent引用的同一视图中的其他地方。以下是几个相关的问题,在答案中使用了这样的解决方案:

>

  • 仅当按下某个命令按钮时才根据需要验证输入
  • 如何仅在未呈现另一个组件的情况下呈现组件?
  • 没有DataModel的JSF 2 dataTable行索引
  • primeFaces依赖的selectOneMenu和required=“true”
  • 当至少有一个字段填满时,根据需要验证一组字段
  • 验证失败时如何更改inputfield和标签的css类?
  • 使用JavaScript获取JSF定义的组件
  • 使用EL表达式将组件ID传递给JSF中的复合组件

    (这只是上个月的事...)

    • 如何在JSF中使用组件绑定,对吗?(会话范围bean中的请求范围组件)
    • 查看范围:java.io.NotSerializableException:javax.faces.component.html.htmlinputtext
    • 绑定属性导致在视图中找到重复的组件ID

  •  类似资料:
    • 问题内容: 在JSF中,每个页面都有一个视图状态,该视图状态与Submit等来回传递。 我知道viewstate是使用页面上各种控件的状态计算得出的,您可以将其存储在客户端或服务器端。 问题是:如何使用此值?是否用于验证在提交时发送的值,以确保同一请求不会发送两次? 另外,它是如何计算的-我意识到Richfaces的计算方式可能与myfaces不同,但是有一个不错的主意。 谢谢。 问题答案: 问题

    • 是因为我的文件名精度设置为秒吗? 是因为我只设置了吗? 或者这是怎么回事? 我的目标是建立一个滚动配置,记录最近5次应用程序运行的情况。

    • 问题内容: 我想在我的JSF Web项目上实现Ajax。我搜索了一下,发现ICEFaces正在通过JSF支持Ajax。但是我不知道它的可用性。 任何人都有Ajax / JSF的经验,请指导我搬到哪里。 [编辑] 如果有人有类似经验,请也分享可用性。好与坏.. 问题答案: JSF 2.0使用f:ajax标记内置了对Ajax的支持。ICEFaces,OpenFaces和RichFaces的所有三个都还

    • 问题内容: 第一次使用Java开发,第一次使用Android开发,因此这是一个新手问题。 我目前有以下代码: 简短问题: 什么是 的.class 属性来完成,f.ex. 在’ C = NewTourny 的.class ‘? 为什么我不能将c转换为Tourny(所有这些类的父类)? 长问题: 目前,这可以处理整个应用程序中的所有按钮导航,并且工作正常。但是,如您所见,当我将c强制转换为Class时

    • 我想让导航栏贴在视区的顶部,一旦用户滚动页面,但它不起作用,我不知道为什么。如果你能帮忙,这里是我的HTML和CSS代码: null null