Spring 3升级至Spring 6后forward跳转路径被篡改引发NoHandlerFoundException问题求助
各位大佬好,我正在把一个基于XML依赖注入的项目从Spring 3升级到Spring 6,碰到了一个诡异的forward跳转问题,折腾好久没解决,来求助大家!
我的项目里有个继承自AbstractCachingViewResolver的TranslatingViewResolver,调试日志显示它正确生成了forward跳转路径:
.TranslatingViewResolver 100159440 | Translating:postpone.noValidDate to forward:/webapp/message?heading=postpone.message.statusError.heading&message=postpone.message.noValidDate (That is an InternalResourceView, btw.)
但紧接着就抛出了找不到映射的异常:
2025-06-16 13:00:34,207 105827 WARN org.springframework.web.servlet.PageNotFound 100159440 | No mapping for GET /fed1/webapp/forward:/webapp/message org.springframework.web.servlet.NoHandlerFoundException: No endpoint GET /fed1/webapp/forward:/webapp/message.
能明显看到原本的forward:/webapp/message被篡改了,前面多了/fed1/webapp/前缀,导致找不到对应的处理器映射,完全搞不懂为啥会这样。
我已经做了这些尝试:
- 查资料说需要用
UrlBasedViewResolver来解析forward跳转,我已经配置了这个解析器,还在log4j2.xml里加了对应的DEBUG日志配置:
<Logger name="org.springframework.web.servlet.view.UrlBasedViewResolver" level="DEBUG"> <AppenderRef ref="MyFile"/> <AppenderRef ref="Console"/> </Logger>
但日志里完全看不到这个类的输出,根本没法排查它的执行情况。
- 我翻了好多关于Spring中
forward:跳转的文档和帖子,感觉配置都是对的,而且在Spring 3版本下运行得好好的,现在实在没头绪了。
更新1
我看了异常的堆栈跟踪:
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.7.jar:6.2.7] at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710) ~[servlet-api.jar:6.1] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130) ~[catalina.jar:11.0.8] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-websocket.jar:11.0.8] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109) ~[catalina.jar:11.0.8] at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:514) ~[catalina.jar:11.0.8] at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:334) ~[catalina.jar:11.0.8] at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:263) ~[catalina.jar:11.0.8] at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171) ~[spring-webmvc-6.2.7.jar:6.2.7]
从堆栈里能看到InternalResourceView持有正确的URL,但当请求回到FrameworkServlet时路径就被篡改了。我没办法调试Tomcat内部的代码,这完全说不通,现在开始怀疑是Tomcat或者Spring的bug了。
更新2
现在我发现可能是双重forward导致的问题:我的代码先被转发到PostponeController,这个控制器判断没有处理逻辑,又转发到消息控制器,但还没到消息控制器就触发了错误。查看请求中的转发信息时,发现它带上了Postpone相关的路径前缀,这个问题出在Tomcat 11的ApplicationHttpRequest.getRequestDispatcher()方法里。我不太清楚这应该怎么正常工作,毕竟之前Spring 3下是好的,现在还在深挖细节,欢迎大家提供思路。
更新3
我一直认为forward:是Spring框架的特性,而不是Servlet引擎的(如果这个理解错了请纠正我),所以不应该把带forward:的路径传给Tomcat,但现在实际情况就是这样。在InternalResourceView.renderMergedOutputModel方法里,有一行代码:
RequestDispatcher rd = getRequestDispatcher(request, dispatcherPath);
这里的dispatcherPath就包含了forward:前缀,我感觉这像是Spring Framework的一个bug?
内容来源于stack exchange

