为什么即使bean是@ ViewScoped,@ PostConstruct回调也会每次触发?联合部队 [英] Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF
问题描述
我正在使用页面上的数据表,并使用binding属性将其绑定到我的backing bean.这是我的代码:-
I am using datatable on page and using binding attribute to bind it to my backing bean. This is my code :-
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:dataTable var="item" value="#{testBean.stringCollection}" binding="#{testBean.dataTable}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" actionListener="#{testBean.action}"/>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
这是我的豆子:-
package managedBeans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlDataTable;
@ManagedBean(name="testBean")
@ViewScoped
public class testBean implements Serializable {
private List<String> stringCollection;
public List<String> getStringCollection() {
return stringCollection;
}
public void setStringCollection(List<String> stringCollection) {
this.stringCollection = stringCollection;
}
private HtmlDataTable dataTable;
public HtmlDataTable getDataTable() {
return dataTable;
}
public void setDataTable(HtmlDataTable dataTable) {
this.dataTable = dataTable;
}
@PostConstruct
public void init(){
System.out.println("Post Construct fired!!");
stringCollection = new ArrayList<String>();
stringCollection.add("a");
stringCollection.add("b");
stringCollection.add("c");
}
public void action(){
System.out.println("Clicked!!");
}
}
请告诉我为什么我每次单击按钮都会触发@PostConstruct?只要我在同一页面上,它应该只触发一次,因为我的bean是@ViewScoped.此外,如果删除绑定属性,则一切正常,并且@PostConstruct回调仅触发一次.那为什么每次我使用绑定属性时呢?我需要绑定属性,并且只想执行一次初始化任务,例如从Web服务中获取数据等.我应该怎么办?我应该在哪里写初始化任务?
Please tell me why is the @PostConstruct firing each and every time i click on button? It should fire only once as long as i am on same page beacause my bean is @ViewScoped. Further, if i remove the binding attribute then everything works fine and @PostConstruct callback fires only once. Then why every time when i use binding attribute? I need binding attribute and want to perform initialisation tasks like fetching data from webservice, etc only once. What should i do? Where should i write my initialisation task?
推荐答案
有趣的是,当您在视图作用域的bean上使用组件绑定时,视图作用域将中断.
Interesting, when you're using component binding on a view scoped bean, the view scope breaks.
我不确定这是否是JSF2中的错误,我必须先阅读整个JSF2规范.到目前为止,您最好的选择是暂时删除组件绑定,并通过新的EL 2.2方法参数语法传递所选项目:
I am not sure if that is a bug in JSF2, I would have to read the entire JSF2 specification first. As far now your best bet is to drop the component binding for now and pass the selected item via new EL 2.2 method argument syntax:
<h:dataTable var="item" value="#{testBean.stringCollection}">
<h:column>
<h:outputText value="#{item}"/>
</h:column>
<h:column>
<h:commandButton value="Click" action="#{testBean.action(item)}"/>
</h:column>
</h:dataTable>
另请参见:
- 我如何传递所选内容到dataTable中commandLink的行?
- 调用直接方法或带有参数的方法/EL中的/变量/参数
-
@ViewScoped
的好处和陷阱 - How can I pass selected row to commandLink inside dataTable?
- Invoke direct methods or methods with arguments / variables / parameters in EL
- Benefits and pitfalls of
@ViewScoped
See also:
更新(2012年12月):这确实是JSF2中的错误.这是个鸡蛋问题.视图范围的Bean以JSF视图状态存储.因此,只有在恢复视图阶段之后,视图范围的Bean才可用.但是,binding
属性在还原视图阶段运行,而视图范围的bean尚不可用.这将导致创建一个全新的视图作用域的bean实例,然后将其替换为存储在恢复的JSF视图状态中的实际视图作用域的bean.
Update (Dec 2012): this is indeed a bug in JSF2. It's a chicken-egg issue. The view scoped beans are stored in the JSF view state. So the view scoped beans are only available after restore view phase. However, the binding
attribute runs during restore view phase, while the view scoped beans are not available yet. This causes creation of a brand new view scoped bean instance, which is then later replaced by the real view scoped bean which was stored in the restored JSF view state.
这被报告为 JSF问题1492 和
This is reported as JSF issue 1492 and JSF spec isssue 787 which will be fixed for JSF 2.2. Until then, your best bet is to use binding
on request scoped beans exclusively, or to look for alternate ways for the particular functional requirement.
更新(2015年3月):JSF 2.2修复程序已反向移植到Mojarra 2.1.18.因此,如果您仍在使用JSF 2.0/2.1,则最好至少升级到该版本.另请参阅什么是JSF中的组件绑定?何时首选使用它?和 JSF2 Facelets中的JSTL ...有道理吗?
Update (Mar 2015): The JSF 2.2 fix was backported to Mojarra 2.1.18. So if you're still using JSF 2.0/2.1, you'd best upgrade to at least that version. See also a.o. What is component binding in JSF? When it is preferred to be used? and JSTL in JSF2 Facelets... makes sense?
这篇关于为什么即使bean是@ ViewScoped,@ PostConstruct回调也会每次触发?联合部队的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!