从IBM WAS8.5.2迁移至Tomcat7时JSF组件ID重复问题求助
解决WAS8.5.2迁移到Tomcat7时JSF动态ID重复的问题
我来帮你拆解这个问题——我之前处理过好几起从WAS迁移到Tomcat时遇到的JSF重复ID问题,本质上是容器对JSF状态保存的处理差异,加上动态ID生成的机制在迁移后没适配好导致的。你遇到的java.lang.IllegalStateException: Component ID main:j_idt56 has already been found in the view错误,核心是会话中保存的旧视图状态没有被正确清理,当新请求生成视图时,自动生成的动态ID和旧视图里的ID撞车了。
下面是几个针对性的解决方案,按优先级从高到低排列:
1. 给所有组件手动指定固定ID(最直接的根治方法)
JSF自动生成的动态ID(比如j_idtXX这种)是最容易引发冲突的根源。你可以遍历所有JSF页面,给没有明确ID的表单、子组件都加上固定的ID,比如:
<!-- 原来的表单 --> <h:form> <h:inputText /> </h:form> <!-- 修改后 --> <h:form id="mainForm"> <h:inputText id="usernameInput" /> </h:form>
这样JSF就不会自动生成随机ID,从根源上避免重复问题。
2. 调整JSF状态保存的配置参数
Tomcat的会话状态处理和WAS差异很大,你可以通过修改web.xml的参数来控制视图状态的保存逻辑:
<!-- 限制会话中保存的视图数量,避免旧视图残留 --> <context-param> <param-name>com.sun.faces.numberOfViewsInSession</param-name> <param-value>1</param-value> </context-param> <context-param> <param-name>com.sun.faces.numberOfLogicalViews</param-name> <param-value>1</param-value> </context-param> <!-- 可选:切换到客户端状态保存,彻底避免服务器端会话状态的冲突 --> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param>
注意:客户端状态保存会把视图状态存在浏览器的隐藏域里,可能会增加请求大小,适合小型项目或测试验证用。
3. 检查Tomcat的类加载隔离,避免JSF版本冲突
WAS有自己的类加载隔离机制,而Tomcat的类加载顺序是先加载项目lib目录的jar,再加载Tomcat自身lib的jar。你需要确保:
- Tomcat的
lib目录下没有残留的jsf-api.jar、jsf-impl.jar(Tomcat7默认不自带JSF,但如果之前部署过其他应用可能会有) - 项目自身的
WEB-INF/lib下只有你指定的javax.faces-2.1.7.jar,没有其他版本的JSF依赖
4. 优化页面提交逻辑,避免重复使用旧视图
如果用户经常通过浏览器后退、重复提交按钮触发问题,可以优化页面的提交逻辑:
- 给
<h:commandButton>添加faces-redirect="true",提交后重定向到新页面,避免旧视图被重复渲染:<h:commandButton value="提交" action="#{bean.submit}" faces-redirect="true" /> - 对于不需要验证的操作,添加
immediate="true",跳过视图状态的恢复直接处理请求。
内容的提问来源于stack exchange,提问作者Rambabu
相关产品推荐
相关产品推荐

