部署到Tomcat非ROOT目录后Java Web Servlet失效,如何修复?
刚把项目从ROOT移到/Test2就踩了404的坑?太正常了——核心问题就是上下文路径(Context Path)从空字符串变成了/Test2,很多你之前没注意到的硬编码路径、相对/绝对路径引用都会因此失效。你说已经改了web.xml的映射,但显然还有其他地方没调整,我给你列几个必查的点:
1. 代码里的硬编码路径必须加上上下文前缀
这是最常见的坑!比如你之前在Servlet里写了:
// 错误写法:直接用绝对路径,会跳转到http://localhost:8080/hello而不是/Test2/hello response.sendRedirect("/hello");
或者在JSP/HTML里写了:
<!-- 错误写法:同样会忽略上下文路径 --> <a href="/login">登录</a> <script src="/js/main.js"></script>
正确的做法是用request.getContextPath()获取当前上下文路径,拼接在前面:
Java代码里:
response.sendRedirect(request.getContextPath() + "/hello"); // 请求转发的话其实不用改,因为getRequestDispatcher的路径是相对于上下文的 request.getRequestDispatcher("/somePage.jsp").forward(request, response);
前端页面里,用EL表达式或者JSTL标签:
<!-- EL表达式写法 --> <a href="${pageContext.request.contextPath}/login">登录</a> <script src="${pageContext.request.contextPath}/js/main.js"></script> <!-- JSTL的<c:url>标签(需要引入JSTL库),会自动处理上下文路径 --> <c:url value="/login" var="loginUrl" /> <a href="${loginUrl}">登录</a>
2. 检查Servlet注解或web.xml的映射是否真的正确
你说已经改了web.xml,但再确认下:不管是@WebServlet注解还是web.xml里的<url-pattern>,都应该用相对于上下文的路径,比如:
// 正确:这个映射会对应http://localhost:8080/Test2/user/list @WebServlet("/user/list")
<!-- web.xml里的正确写法 --> <servlet-mapping> <servlet-name>UserServlet</servlet-name> <url-pattern>/user/list</url-pattern> </servlet-mapping>
别写成绝对路径(比如/Test2/user/list),因为Tomcat会自动把上下文路径加上,重复加的话就会变成/Test2/Test2/user/list,肯定404。
3. 确认Tomcat的部署配置是否正确
- 如果是用war包部署,确保你的war包名字是
Test2.war——Tomcat默认会把war包的文件名作为上下文路径,除非你手动配置。 - 如果是文件夹部署,确保项目文件夹放在
webapps/Test2下面,而不是嵌套在其他文件夹里。 - 如果你手动在
server.xml或者conf/Catalina/localhost/Test2.xml里配置了Context,检查path属性是不是设成了/Test2,别写错或者重复设置:
<!-- Test2.xml的正确配置示例 --> <Context docBase="/path/to/your/project" path="/Test2" reloadable="true" />
4. 检查过滤器或拦截器的路径配置
如果项目里有Filter或者Interceptor,它们的路径映射同样要注意上下文路径的问题。比如Filter的<url-pattern>如果写成/*,那是相对于上下文的,没问题;但如果硬编码了具体路径,也要确保是相对路径,或者用上下文前缀拼接。
5. 清理缓存并重启Tomcat
有时候Tomcat会缓存旧的部署配置,尤其是你之前在ROOT目录部署过。建议:
- 删掉
work/Catalina/localhost/Test2目录下的缓存文件 - 重启Tomcat,确保新的上下文路径生效
按上面的步骤排查一遍,应该能解决大部分404的问题。如果还是不行,可以看看Tomcat的日志(logs/localhost.log或者localhost_access_log.*.txt),里面会记录具体的请求路径,能帮你定位到底是哪个路径写错了。
内容的提问来源于stack exchange,提问作者namila007

