JSF中@ViewScoped/@SessionScoped Bean每次请求后重启问题
我之前也碰到过类似的Bean生命周期异常,结合你给出的环境(JSF 2.2.13、PrimeFaces 6.0、Tomcat 7.0.42、Mojarra 2.2.13)和现象,咱们一步步拆解排查:
可能的原因及排查步骤
1. Tomcat类加载冲突(最常见)
Tomcat 7的类加载机制如果遇到重复依赖,很容易导致Bean被多次加载。你可以先检查这两点:
- 看看
WEB-INF/lib下有没有重复的JSF/Mojarra JAR(比如同时存在jsf-api.jar和javax.faces-api.jar); - 检查Tomcat全局库目录(
CATALINA_HOME/lib)里有没有遗留的旧版本JSF相关包,要是有,直接删掉——因为你项目里已经带了Mojarra 2.2.13,全局库的同类型包会造成类加载冲突,导致Bean实例反复初始化。
2. Bean序列化问题(针对@ViewScoped)
JSF 2.2的@ViewScoped要求Bean必须实现Serializable接口,要是没实现,视图状态保存/恢复时就会触发Bean重新创建。哪怕你说@SessionScoped也有问题,先确认你的Bean写法是否正确:
@ViewScoped @ManagedBean public class TestBean implements Serializable { // 成员变量、业务方法 private String testValue; // 构造方法里加个日志,方便追踪实例 public TestBean() { System.out.println("TestBean 初始化,哈希值:" + this.hashCode()); } }
另外,PrimeFaces 6.0和JSF 2.2的兼容性没问题,但要是用了自定义组件或者复杂AJAX请求,也可能干扰视图状态,你可以先简化页面,只保留Write/Read按钮和基础逻辑,看看问题是否还存在。
3. 会话丢失导致@SessionScoped Bean重启
如果@SessionScoped Bean也重启,大概率是会话没维持住:
- 先看浏览器Cookie是否禁用了——JSF默认用Cookie跟踪会话,禁用Cookie的话会话会丢失;
- 检查Tomcat的
context.xml配置,看看会话相关参数(比如sessionTimeout、sessionCookiePath)是否合理,有没有开启会话持久化但配置错误; - 查看Tomcat访问日志(
localhost_access_log.*.txt),对比两次请求的会话ID(JSESSIONID),如果ID不一样,说明会话确实丢失了,Bean自然会重新创建。
4. Maven依赖冲突
用Maven命令mvn dependency:tree导出依赖树,检查是否有其他依赖偷偷引入了不同版本的Mojarra或PrimeFaces。比如有些第三方组件可能会带旧版JSF依赖,这时候要排除掉:
<dependency> <groupId>某个第三方库</groupId> <artifactId>xxx</artifactId> <version>x.x.x</version> <exclusions> <exclusion> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> </exclusion> <exclusion> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> </exclusion> </exclusions> </dependency>
同时确保你的核心依赖版本统一,不要混用不同版本的JSF组件。
5. 视图状态保存配置
检查web.xml里的视图状态保存方式:
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param>
如果用的是client模式,必须保证Bean的所有成员变量都能序列化(包括嵌套对象),否则视图恢复失败会触发Bean重启。服务器端模式的话,还要确认Tomcat的会话存储是否正常,比如有没有配置分布式会话但环境不支持。
额外建议
对比你那个“正常的项目”,把两个项目的web.xml、context.xml、Maven依赖列表一一对比,找出差异点——很多时候问题就藏在这些细节里。另外,Tomcat 7.0.42版本比较老,要是条件允许,升级到Tomcat 7的最新稳定版或者Tomcat 8,能解决不少已知的类加载和会话管理bug。
内容的提问来源于stack exchange,提问作者rflobao

