Servlet的urlPatterns设为/display/*失效,Tomcat报500栈溢出错误求助
问题分析与解决方案
这问题我之前排查过好几次,核心是相对路径的请求转发+Servlet的通配符映射规则导致了无限递归调用,直接把栈给撑爆了,所以才会抛出StackOverflowError。
为什么会出现循环?
当你把Servlet的urlPatterns设为"/display/*"时,Tomcat会把所有以/display/开头的请求都交给这个DisplayView处理。而你的doGet方法里用的是相对路径转发:
request.getRequestDispatcher(landingPage).forward(request, response); // landingPage是"WEB-INF/jsps/display.jsp",没有以/开头
这里的相对路径是相对于当前Servlet的映射路径来解析的:
- 假设用户访问
http://localhost:8080/yourApp/display/test,当前Servlet的映射路径是/display/,那么相对路径会被解析成/display/WEB-INF/jsps/display.jsp - 这个新路径依然匹配
/display/*的规则,所以Tomcat又会调用DisplayView的doGet方法 - 然后再次转发、再次匹配,无限循环下去,直到栈内存耗尽,抛出
StackOverflowError
而当你用"/display"作为urlPattern时,Servlet的映射路径是/display,相对路径会被解析成/WEB-INF/jsps/display.jsp,这个路径不匹配/display,所以会交给JSP的默认Servlet处理,自然就正常了。
怎么解决?
最简单的修复方式就是把转发路径改成绝对路径(以/开头),这样路径解析会直接基于上下文根,不会受当前Servlet的映射影响:
修改DisplayView里的landingPage常量:
public static final String landingPage = "/WEB-INF/jsps/display.jsp";
这样不管你的Servlet用/display/*还是其他通配符映射,转发的目标路径都是/WEB-INF/jsps/display.jsp,不会再触发当前Servlet的重复调用,循环问题就解决了。
额外提醒
- 尽量在请求转发时使用绝对路径,避免因Servlet映射规则变化导致的路径解析问题
- 如果一定要用相对路径,要确保解析后的路径不会匹配当前Servlet的映射规则,不过绝对路径显然更稳妥
内容的提问来源于stack exchange,提问作者ErShakirAnsari
相关产品推荐
相关产品推荐

