我再次看到@PostConstruct每次都在触发,即使没有使用绑定属性。请参阅此代码: -
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<c:forEach var="item" items="#{TestBean.listItems}">
<h:outputText value="#{item}"/>
</c:forEach>
<h:commandButton value="Click" actionListener="#{TestBean.actionListener}"/>
</h:form>
</h:body>
</html>
这是JSF中最简单的bean: -
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;
@ManagedBean(name="TestBean")
@ViewScoped
public class TestBean implements Serializable {
private List<String> listItems;
public List<String> getListItems() {
return listItems;
}
public void setListItems(List<String> listItems) {
this.listItems = listItems;
}
public TestBean() {
}
@PostConstruct
public void init(){
System.out.println("Post Construct fired!");
listItems = new ArrayList<String>();
listItems.add("Mango");
listItems.add("Apple");
listItems.add("Banana");
}
public void actionListener(){
System.out.println("Action Listener fired!");
}
}
您是否看到任何应该导致postconstruct回调每次触发的行为?我认为JSF 2.0非常不稳定。如果每次@ViewScoped服务的目的都必须触发PostConstruct。为什么不使用@RequestScoped?我以为我在申请中犯了一些错误。但是当我在JSF中创建这个最简单的时候,我仍然会遇到这个错误。我不了解JSF的范围吗?或者他们没有正确测试?此外,如果你删除c:forEach并用ui:repeat替换它,那么它可以正常工作。
等待回复以确认是否是错误或是否有意阻止程序员使用jstl?
答案 0 :(得分:13)
此问题与您之前回答的问题具有相同的理由:Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF。
这确实是JSF2中的一个错误。这是一个鸡蛋问题。视图范围bean存储在JSF视图状态中。因此视图范围bean仅在还原视图阶段后可用。但是,JSTL标记在还原视图阶段运行,而视图范围Bean尚不可用。这会导致创建一个全新的视图范围的bean实例,然后由实际的视图范围bean替换,该实例存储在已恢复的JSF视图状态中。
报告为JSF issue 1665和JSF spec isssue 787,这是针对JSF 2.2修复的,并在Mojarra 2.1.18中移植。因此,只需升级到Mojarra 2.1.18即可。
如果无法升级,那么最好的办法是在请求/会话/应用程序作用域上独占使用JSTL标记,或者寻找特定功能需求的替代方法。您可以将<c:forEach>
替换为您已发现的<ui:repeat>
。