罪魁祸首
在一次无意间引入注解@EnableWebMvc导致了swagger404问题
排查思路
404原因
我按照MVC的请求执行流程找到了DispatcherServlet#doDispatch这个核心方法中
我debug发现他在获取HandlerMapping执行链的时候为空导致的404问题。于是我便注释掉这个注解查看一下正常获取的HandlerMapping是什么。
这是放开注解后发现/swagger-ui.html这个请求获得的HandlerMapping执行链是从SimpleUrlHandlerMapping这个中获取的。
SimpleUrlHandlerMapping没有被注册为Bean的原因
先说明一下刚刚获取HandlerMapping执行链是从handlerMappings这个集合中获取的,这个集合中的数据是从Bean容器中获取的,SimpleUrlHandlerMapping不存在其实就是他没有被注册为Bean。
顺着这个类的调用方,找到了注册他的类ResourceHandlerRegistry,最终定位到了WebMvcConfigurationSupport#resourceHandlerMapping()方法中。
先看registry.getHandlerMapping()方法
由此可以得出registrations只要不为空就一定可以注册成功SimpleUrlHandlerMapping。
接着就要找一下那里往这个值中增加数据的。
一路追踪下去
调用在WebMvcAutoConfiguration#addResourceHandlers()方法中,回到刚刚框住的addResourceHandler方法。
这个方法其实就是上面WebMvcAutoConfiguration的往registrations追加数据的方法,只要delegates中存放了WebMvcAutoConfiguration就可以正常注册SimpleUrlHandlerMapping。
这里也就得出@EnableWebMvc造成了WebMvcAutoConfiguration没有注册为Bean。
WebMvcAutoConfiguration没有被注册为Bean的原因
@EnableWebMvc做了点什么
EnableWebMvc注解导入了DelegatingWebMvcConfiguration作为Bean,DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport
WebMvcAutoConfiguration
@ConditionalOnMissingBean 会识别到 参数中的类 的继承树,当容器中存在 该类 或 该类的子类 或 该类的父类 的类型时,@ConditionalOnMissingBean 返回false ,使得 @ConditionalOnMissingBean 标注的类 不执行。
总结
@EnableWebMvc注解会全面接管SpringMVC,导致WebMvcAutoConfiguration无法自动注入,促使SimpleUrlHandlerMapping无法作为Bean,/swagger-ui.html没办法正常获取适配器而失效。