Wildfly Docker镜像与原生部署差异及Spring WAR部署报错排查
我有一个基于SpringFramework 5.3构建的WAR应用,将其复制到本地默认安装的Wildfly 27的deployments目录即可正常部署,无需对Wildfly默认配置做任何修改。但尝试基于quay.io/wildfly/wildfly:27.0.0.Final-jdk17构建Docker镜像,将同一份WAR包复制到/opt/jboss/wildfly/standalone/deployments/目录后,构建成功但运行时出现大量类似错误:
Failed to define class org.springframework.web.servlet.DispatcherServlet in Module "deployment..war" from Service Module Loader: java.lang.NoClassDefFoundError: Failed to link org/springframework/web/servlet/DispatcherServlet (Module "deployment..war" from Service Module Loader): Failed to link org/springframework/web/servlet/FrameworkServlet (Module "deployment..war" from Service Module Loader): Failed to link org/springframework/web/servlet/HttpServletBean (Module "deployment..war" from Service Module Loader): javax/servlet/http/HttpServlet
现提出以下问题:
- 为何Docker镜像的表现与原生部署不同?
- 是否需要在Wildfly Docker部署中排除某些模块?如果需要,应排除哪些?
1. 原生与Docker镜像表现差异的原因
官方Wildfly Docker镜像默认启用Jakarta EE 9+兼容模式,而本地默认安装的Wildfly 27默认采用Jakarta EE 8兼容模式(保留了对javax.servlet命名空间的兼容)。Spring Framework 5.3依赖的是旧版javax.servlet包,而Jakarta EE 9+已将Servlet API迁移到jakarta.servlet命名空间,两者命名空间不兼容,导致Docker镜像运行时找不到javax.servlet.http.HttpServlet类,触发NoClassDefFoundError。
本地Wildfly默认配置未强制启用Jakarta EE 9模式,因此能正常加载Spring依赖的javax.servlet类,而Docker镜像的默认配置适配Jakarta EE 9+,进而出现冲突。
2. 解决方案:无需排除模块,切换兼容模式即可
优先推荐通过启动参数切换Wildfly到Jakarta EE 8兼容模式,操作更简单且不易引发其他问题:
- 在Dockerfile中修改启动命令,添加兼容模式参数:
CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone.xml", "-Dee8.preview.mode=true"]
如果一定要通过排除模块解决,需在WAR包的WEB-INF/jboss-deployment-structure.xml中添加如下配置,排除Wildfly自带的Jakarta Servlet模块,但此方式可能引发其他依赖冲突,不推荐:
<jboss-deployment-structure> <deployment> <exclusions> <module name="jakarta.servlet.api"/> </exclusions> </deployment> </jboss-deployment-structure>
内容的提问来源于stack exchange,提问作者Rollins999

