JSTL c:forEach导致@ViewScoped bean在每个请求上调用@PostConstruct

我再次看到@PostConstruct每次都在触发,即使没有使用绑定属性。 看到这段代码: –

    Facelet Title           

这是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 listItems; public List getListItems() { return listItems; } public void setListItems(List listItems) { this.listItems = listItems; } public TestBean() { } @PostConstruct public void init(){ System.out.println("Post Construct fired!"); listItems = new ArrayList(); 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?

这个问题与你之前回答的问题有相同的理由: 为什么@PostConstruct回调每次都会触发,即使bean是@ViewScoped? JSF 。

这确实是JSF2中的一个错误。 这是一个鸡蛋问题。 视图范围的bean存储在JSF视图状态中。 因此,视图范围bean仅在还原视图阶段后可用。 但是,JSTL标记在还原视图阶段运行,而视图范围bean尚不可用。 这会导致创建一个全新的视图范围的bean实例,然后由实际的视图范围bean替换,该bean存储在恢复的JSF视图状态中。

这被报告为JSF问题1665和JSF规范isssue 787 ,它已针对JSF 2.2修复并移植回Mojarra 2.1.18。 所以,只需升级到Mojarra 2.1.18即可。

如果您无法升级,那么最好的办法是在请求/会话/应用程序作用域上使用JSTL标记,或者寻找特定function需求的替代方法。 您可以使用替换 ,如您所知。

也可以看看:

  • JSF 2.0中的通信 – @ViewScoped在taghandler中失败
  • JSF2 Facelets中的JSTL有意义吗?