一个注解导致swagger无法访问

65 阅读2分钟

罪魁祸首

  在一次无意间引入注解@EnableWebMvc导致了swagger404问题

image.png

排查思路

404原因

我按照MVC的请求执行流程找到了DispatcherServlet#doDispatch这个核心方法中 image.png 我debug发现他在获取HandlerMapping执行链的时候为空导致的404问题。于是我便注释掉这个注解查看一下正常获取的HandlerMapping是什么。 image.png 这是放开注解后发现/swagger-ui.html这个请求获得的HandlerMapping执行链是从SimpleUrlHandlerMapping这个中获取的。

SimpleUrlHandlerMapping没有被注册为Bean的原因

先说明一下刚刚获取HandlerMapping执行链是从handlerMappings这个集合中获取的,这个集合中的数据是从Bean容器中获取的,SimpleUrlHandlerMapping不存在其实就是他没有被注册为Bean。

image.png 顺着这个类的调用方,找到了注册他的类ResourceHandlerRegistry,最终定位到了WebMvcConfigurationSupport#resourceHandlerMapping()方法中。

image.png 先看registry.getHandlerMapping()方法

image.png 由此可以得出registrations只要不为空就一定可以注册成功SimpleUrlHandlerMapping。
接着就要找一下那里往这个值中增加数据的。

image.png 一路追踪下去

image.png 调用在WebMvcAutoConfiguration#addResourceHandlers()方法中,回到刚刚框住的addResourceHandler方法。

image.png 这个方法其实就是上面WebMvcAutoConfiguration的往registrations追加数据的方法,只要delegates中存放了WebMvcAutoConfiguration就可以正常注册SimpleUrlHandlerMapping。
这里也就得出@EnableWebMvc造成了WebMvcAutoConfiguration没有注册为Bean。

WebMvcAutoConfiguration没有被注册为Bean的原因

@EnableWebMvc做了点什么

image.png

image.png EnableWebMvc注解导入了DelegatingWebMvcConfiguration作为Bean,DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport

WebMvcAutoConfiguration

image.png @ConditionalOnMissingBean 会识别到 参数中的类 的继承树,当容器中存在 该类 或 该类的子类 或  该类的父类 的类型时,@ConditionalOnMissingBean 返回false ,使得 @ConditionalOnMissingBean 标注的类 不执行。

总结

  @EnableWebMvc注解会全面接管SpringMVC,导致WebMvcAutoConfiguration无法自动注入,促使SimpleUrlHandlerMapping无法作为Bean,/swagger-ui.html没办法正常获取适配器而失效。