WebLogic迁移JBoss EAP7.4时JSF表单action含null前缀致404问题
问题根源
1. null值的来源
<h:form>渲染后action中的null,本质是JSF在生成回发URL时无法正确获取应用上下文根(context root)。JBoss EAP默认使用的Mojarra(JSF参考实现)与WebLogic的上下文路径解析逻辑存在差异:WebLogic会在部分场景下自动填充上下文根,而Mojarra如果无法通过ExternalContext.getRequestContextPath()获取有效值,就会将null拼接进URL,导致null/mywebapp/pages/mypage.xhtml这种错误路径。
常见触发原因:
- web.xml中JSF Servlet映射配置不符合Mojarra预期
- 应用上下文根未明确配置,Mojarra无法自动识别
- 容器自带JSF库与项目引入的版本冲突,导致URL生成逻辑异常
2. 为何不能直接回发至mypage.xhtml
JSF表单回发必须经过核心的FacesServlet处理,它负责管理JSF生命周期、解析请求参数、匹配视图并调用后端业务逻辑。直接指向mypage.xhtml会绕过Servlet,即使能访问页面也无法处理表单提交的业务流程,且原本的问题是连正确的Servlet路径都未生成,才出现了带null的错误URL。
解决步骤
步骤1:修正web.xml中的JSF Servlet配置
确保FacesServlet的映射规则适配Mojarra,建议使用*.xhtml直接映射(WebLogic原配置可能为*.faces):
<servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
该配置让JSF直接处理所有.xhtml请求,确保回发URL生成逻辑能正确关联到Servlet路径。
步骤2:明确配置应用上下文根
在WAR包的WEB-INF目录下创建jboss-web.xml,强制指定上下文根:
<jboss-web> <context-root>/mywebapp</context-root> </jboss-web>
避免Mojarra自动识别上下文根时出现异常,确保getRequestContextPath()返回正确的值。
步骤3:调整JSF上下文参数
在web.xml中添加以下参数,优化Mojarra的URL生成与解析逻辑:
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>server</param-value> </context-param> <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Production</param-value> </context-param> <context-param> <param-name>com.sun.faces.expressionFactory</param-name> <param-value>com.sun.el.ExpressionFactoryImpl</param-value> </context-param>
com.sun.faces.expressionFactory参数可确保Mojarra使用正确的EL解析器,避免上下文路径解析异常。
步骤4:排除容器自带JSF库(若版本冲突)
如果切换JSF版本后问题依旧,说明JBoss自带的JSF库与项目依赖冲突。在WAR包的WEB-INF目录下创建jboss-deployment-structure.xml,强制使用项目引入的JSF版本:
<jboss-deployment-structure> <deployment> <exclusions> <module name="javax.faces.api" /> <module name="com.sun.jsf-impl" /> </exclusions> <dependencies> <module name="javax.faces.api" export="true" /> <module name="com.sun.jsf-impl" export="true" /> </dependencies> </deployment> </jboss-deployment-structure>
步骤5:验证页面视图根配置
确保页面包含正确的<f:view>标签,辅助JSF解析上下文信息:
<f:view contentType="text/html"> <h:form id="search" onkeypress="submitOnEnter(event, this.id);"> <!-- 表单内容 --> </h:form> </f:view>
验证
重新部署应用后,查看浏览器渲染的form标签action属性,若显示为/mywebapp/pages/mypage.xhtml则配置生效,表单提交将正常进入JSF生命周期,不再返回404错误。
内容的提问来源于stack exchange,提问作者user3804769

