Docker部署Tomcat运行war包访问Servlet返回404如何解决
问题根因
核心是tomcat:latest镜像的版本兼容性问题:
- 目前Tomcat官方的latest标签对应Tomcat 10及以上版本,该版本将原JavaEE体系的
javax.servlet全套类的包命名空间全部替换为JakartaEE的jakarta.servlet。你代码中使用的@WebServlet注解属于javax.servlet.annotation包,Tomcat 10+无法识别该注解,也就不会注册对应的接口路由,因此访问返回404。 - 你本地IntelliJ启动的Tomcat是9及以下版本,仍然支持
javax.servlet包,所以可以正常访问接口。
解决方法
两种方案任选其一即可:
方案1:降级Docker基础镜像(无需修改代码)
直接把Dockerfile中的基础镜像替换为Tomcat 9版本即可,参考配置:
# 可根据自身JDK版本选择对应Tomcat 9的镜像标签 FROM tomcat:9.0.80-jdk17 ADD example.war /usr/local/tomcat/webapps/ EXPOSE 8080 CMD ["/usr/local/tomcat/bin/catalina.sh", "run"]
修改后重新构建镜像、启动容器即可正常访问。
方案2:适配Tomcat 10+(无需修改镜像)
把代码中所有servlet相关的导入包前缀从javax替换为jakarta,修改后代码如下:
package io.bananahammock.bananahammock_backend; import java.io.*; import jakarta.servlet.http.*; import jakarta.servlet.annotation.*; @WebServlet(name = "helloServlet", value = "/hello-servlet") public class HelloServlet extends HttpServlet { private String message; public void init() { message = "Hello World!"; } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><body>"); out.println("<h1>" + message + "</h1>"); out.println("</body></html>"); } public void destroy() { } }
修改后重新打包war包,再构建镜像启动即可。
额外排查点:如果修改后仍有问题,检查项目
WEB-INF/web.xml头部是否配置了metadata-complete="true",该配置会关闭Servlet注解扫描功能,改为false即可。
内容的提问来源于stack exchange,提问作者Copainbig
相关产品推荐
相关产品推荐

