在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运行以返回User
bean的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>
绑定
存储在哪里?
当构建/还原JSF视图(Facelets/JSP文件)时,将生成一个JSF组件树。此时,视图构建时,所有binding
属性都将被评估(以及id
attribtues和像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线程,甚至一些“奇怪的”IndexoutOfboundsException
或ConcurrentModificationException
直接来自JSF实现源代码,而JSF正忙于保存或恢复视图状态(即堆栈跟踪指示
无论如何,以这种方式使用绑定
,将整个组件实例绑定到bean属性,即使是在请求作用域bean上,在JSF2.x中也是相当罕见的用例,通常不是最佳实践。它预示着一种设计气味。您通常在视图端声明组件,并将它们的运行时属性(如value
,以及styleclass
、disabled
、rendered
等)绑定到普通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
引用的同一视图中的其他地方。以下是几个相关的问题,在答案中使用了这样的解决方案:
>
使用EL表达式将组件ID传递给JSF中的复合组件
(这只是上个月的事...)
问题内容: 在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