这似乎不对。我正在清理我的代码,我只是注意到了这一点。每个ajax请求都会触发我的@PostConstruct
bean的构造函数和@ViewScoped
。即使是一个简单的数据库分页也会解雇它。
我understood @ViewScoped
超过@RequestScoped
且不应在每次请求时重建。{{1}}只有在通过GET重新加载完整页面之后。
答案 0 :(得分:50)
换句话说,您的@ViewScoped
bean的行为类似于@RequestScoped
bean。它在每次回发请求时都是从头开始重新创建的。造成这种情况的原因有很多种,其中大多数原因归结为JSF状态中的相关JSF视图不再可用,而JSF状态又默认与HTTP会话相关联。
如果您可以确保HTTP会话本身不是问题的根本原因,即当@SessionScoped
工作正常时,请查看以下可能原因列表。否则,如果HTTP会话本身也在每个请求上被删除并重新创建,那么您需要退后一步并查看会话cookie和服务器配置。与HTTP会话损坏相关的任何原因至少超出了JSF的上下文。
您正在使用Mojarra 2.1.17或更早版本,该视图包含EL表达式,它将视图范围的bean属性绑定到在view build time期间评估的标记属性。示例包括JSTL <c:if>
,<c:forEach>
等,或JSF <ui:include>
,<x:someComponent id="#{...}"
,<x:someComponent binding="#{...}">
等。这是由Mojarra中的错误引起的({{3 }})。另请参阅issue 1492
这已在Mojarra 2.1.18版中修复。如果您无法升级到较新版本,则解决方法是在web.xml
中禁用部分状态保存,如下所示,另请参阅Why does @PostConstruct callback fire every time even though bean is @ViewScoped? JSF
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
或者,当您只想定位一组特定的JSF视图时:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value>
</context-param>
重要的是,将JSF组件的id
或binding
属性的值绑定到视图范围的bean属性是一种不好的做法。这些应该真正绑定到请求范围的bean属性,或者应该寻求替代方案。另请参阅JSTL in JSF2 Facelets... makes sense?
您正在使用Mojarra 2.2.0,只有该版本在维护2.2.1中已修复的视图范围方面存在(但未知)错误,另请参阅How does the 'binding' attribute work in JSF? When and how should it be used?。解决方案是升级到更新版本。
从错误的包导入@ViewScoped
注释。 JSF提供了两个@ViewScoped
注释,一个来自javax.faces.bean
包,用于使用@ManagedBean
注释的JSF托管bean,另一个来自javax.faces.view
包,用于注释@Named
的CDI托管bean }。当bean范围注释与bean管理批注不匹配时,实际的bean范围将成为bean管理框架的默认范围,即JSF托管bean中的@RequestScoped
和CDI托管bean中的@Dependent
。
您需要确保拥有以下任一构造,并且不要混用它们,另请参阅issue 2912。
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class CorrectJSFViewScopedBean implements Serializable {
import javax.inject.Named;
import javax.faces.view.ViewScoped;
@Named
@ViewScoped
public class CorrectCDIViewScopedBean implements Serializable {
视图(意外?)标记为瞬态<f:view transient="true">
。这基本上打开了“无状态JSF”,这是自Mojarra 2.1.19以来的新功能。因此,JSF视图根本不会保存在JSF状态中,并且逻辑结果是所有引用的视图范围bean都不能再与JSF视图关联。另请参阅@ViewScoped bean recreated on every postback request when using JSF 2.2
在错误尝试“避免”com.sun.faces.enableRestoreView11Compatibility
的情况下,将true
上下文参数设置为ViewExpiredException
,将Web应用程序配置为ViewExpiredException
。使用此上下文参数,将永远不会抛出/WEB-INF/lib
,但是将从头开始重新创建视图(以及所有关联的视图范围bean)。但是,如果每次请求都发生这种情况,那么这种方法实际上隐藏了另一个问题:视图过早过期。这表明维护JSF视图状态和/或HTTP会话可能存在问题。如何正确地解决/配置,前往What is the usefulness of statelessness in JSF?。
Web应用程序的运行时类路径受到多个不同版本化的JSF API或impl相关类的污染。这会导致JSF视图状态的标识符/标记损坏/不匹配。您需要确保webapp的<scope>provided</scope>
中没有多个JSF API JAR文件。如果您使用的是Maven,请仔细确保将服务器提供的库标记为<p:dialog>
。另请参阅javax.faces.application.ViewExpiredException: View could not be restored中的“安装JSF”部分以及相关问题的答案:our JSF wiki page。
当您使用PrimeFaces <p:dialog>
时,请确保<h:form>
拥有自己的<h:form>
并且它不会嵌套在另一个FileUploadFilter
中。另请参阅How to properly install and configure JSF libraries via Maven?。
当您将PrimeFaces FileUploadFilter
与PrettyFaces合并时,请确保@ViewScoped
也可以在PrettyFaces重写/转发的请求上运行。另请参阅p:fileUpload inside p:dialog losing @ViewScoped values和ViewScoped bean rebuilt when FileUploadListener called using PrettyFaces。
当您使用PrettyFaces时,一个配置错误的重写规则会将CSS / JS /图像资源重定向到绑定到{{1}} bean的JSF页面,这也会产生误导性行为。另请参阅How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable。