这似乎不对。我正在清理我的代码,我才注意到这一点。每个 ajax 请求都在触发构造函数和@PostConstruct
我的@ViewScoped
bean。即使是简单的数据库分页也会触发它。
我知道这比每次请求@ViewScoped
都更长,@RequestScoped
并且不应该重建它。只有在通过 GET 重新加载完整的页面后。
这似乎不对。我正在清理我的代码,我才注意到这一点。每个 ajax 请求都在触发构造函数和@PostConstruct
我的@ViewScoped
bean。即使是简单的数据库分页也会触发它。
我知道这比每次请求@ViewScoped
都更长,@RequestScoped
并且不应该重建它。只有在通过 GET 重新加载完整的页面后。
换句话说,你的@ViewScoped
bean 的行为就像一个@RequestScoped
bean。它在每个回发请求中都从头开始重新创建。这有很多可能的原因,其中大部分归结为相关的 JSF 视图在 JSF 状态下不再可用,而 JSF 状态又默认与 HTTP 会话相关联。
前提是您可以确保 HTTP 会话本身不是问题的根本原因,即当@SessionScoped
工作绝对正常时,请查看下面的可能原因列表。否则,如果 HTTP 会话本身也被丢弃并在每个请求上重新创建,那么您需要退后一步,查看会话 cookie 和服务器配置。任何与 HTTP 会话中断相关的原因至少超出了 JSF 的上下文。
您使用的是 Mojarra 2.1.17 或更早版本,并且视图包含 EL 表达式,这些表达式将视图范围的 bean 属性绑定到在视图构建时评估的标记属性。示例是 JSTL <c:if>
, <c:forEach>
, 等或 JSF <ui:include>
, <x:someComponent id="#{...}"
,<x:someComponent binding="#{...}">
等。这是由 Mojarra 中的错误引起的(问题 1496)。另请参阅为什么 @PostConstruct 回调每次都会触发,即使 bean 是 @ViewScoped?JSF
这已在 Mojarra 版本 2.1.18 中修复。如果您无法升级到较新版本,解决方法是禁用部分状态保存,如下所示web.xml
,另请参阅JSF2 Facelets 中的 JSTL... 有意义吗?
<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 属性,或者应该寻求替代方案。另请参阅JSF 中的“绑定”属性如何工作?何时以及如何使用它?
您使用的是 Mojarra 2.2.0,只有该版本在维护 2.2.1 中已修复的视图范围方面存在(尚未知)错误,另请参见问题 2916。解决方案是升级到较新的版本。
@ViewScoped
注释是从错误的包中导入的。JSF 提供了两种@ViewScoped
注解,一种来自javax.faces.bean
用 注释的 JSF 托管 bean 的包@ManagedBean
,另一种来自javax.faces.view
用 注释的 CDI 托管 bean的包@Named
。当 bean 范围注解与 bean 管理注解不匹配时,实际的 bean 范围将成为 bean 管理框架的默认范围,即@RequestScoped
在 JSF 托管 bean 和@Dependent
CDI 托管 bean 中。
您需要确保您具有以下任一构造并且不要混合它们,另请参阅使用 JSF 2.2 时在每个回发请求上重新创建的 @ViewScoped bean。
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 视图相关联。另请参阅JSF 中无状态的用处是什么?
Web 应用程序配置了com.sun.faces.enableRestoreView11Compatibility
上下文参数设置true
为“避免”的错误尝试ViewExpiredException
。使用此上下文参数,ViewExpiredException
将永远不会抛出,但视图(以及所有关联的视图范围 bean)只会从头开始重新创建。但是,如果每个请求都发生这种情况,那么这种方法实际上隐藏了另一个问题:视图过期太快了。这表明在维护 JSF 视图状态和/或 HTTP 会话时可能存在问题。如何正确解决/配置该问题,请前往javax.faces.application.ViewExpiredException: View could not be restore。
Web 应用程序的运行时类路径被多个不同版本的 JSF API 或 impl 相关类污染。这会导致 JSF 视图状态的标识符/标记出现损坏/不匹配。您需要确保 webapp 中没有多个 JSF API JAR 文件/WEB-INF/lib
。如果您使用 Maven,请确保将服务器提供的库标记为<scope>provided</scope>
. 另请参阅我们的 JSF wiki 页面中的“安装 JSF”部分以及此相关问题的答案:如何通过 Maven 正确安装和配置 JSF 库?.
当您使用 PrimeFaces 时,请<p:dialog>
确保它<p:dialog>
有自己的<h:form>
并且它没有嵌套在另一个中<h:form>
。另请参阅p:dialog 中的 p:fileUpload 丢失 @ViewScoped 值。
当您将 PrimeFacesFileUploadFilter
与 PrettyFaces 结合使用时,请确保它们FileUploadFilter
也在 PrettyFaces 重写/转发的请求上运行。另请参阅使用 PrettyFaces 调用 FileUploadListener 时重建 ViewScoped bean和如何使用 PrimeFaces p:fileUpload? 侦听器方法永远不会被调用或 UploadedFile 为空/抛出错误/不可用。
当您使用 PrettyFaces 时,将 CSS/JS/图像资源重定向到绑定到@ViewScoped
bean 的 JSF 页面的错误配置的重写规则也会产生误导行为。另请参阅CDI ViewScope 和 PrettyFaces:多次调用 @PostConstruct (JSF 2.2)。