在做项目的时候,给拦截器如果加上@EnableWebMvc注解会导致静态的资源加载不进来,而使用@Configuration就不会出现这个问题,虽然我没遇到,但是我看到了这个问题,就顺便把这个问题记录下来,并从源码中分析一下这个注解。
@Configuration
@EnableWebMvc
public class webConfig implements WebMvcConfigurer {
@Autowired
private SessionInterceptor sessionInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(sessionInterceptor).addPathPatterns("/**");
}
}
进入EnableWebMvc的源码如下,
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
可以很明显的发现**@Import(DelegatingWebMvcConfiguration.class)**这行代码,这不就是WebMvcConfigurationSupport的子类么,是专门来配置Mvc的一些配置,并加载各种WebMvc的配置。
@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
//用来加载所有的WebMvcConfiguer配置,这也就是说我们也可以自定义WebMvcConfiguer,它会自动的搜索并加载。
//AutoWired注解后边默认required=true,表示的是要注入的这些必须存在不然就会报错,当选为false的时候,如果没有就直接跳过了
@Autowired(required = false)
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
//配置路径匹配
@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
this.configurers.configurePathMatch(configurer);
}
//是一个内容协商配置
@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
this.configurers.configureContentNegotiation(configurer);
}
//异步支持配置
@Override
protected void configureAsyncSupport(AsyncSupportConfigurer configurer) {
this.configurers.configureAsyncSupport(configurer);
}
//也是用来处理静态资源文件的,WEB-INF
@Override
protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
this.configurers.configureDefaultServletHandling(configurer);
}
//格式转换器,比如我们的输入输出格式等
@Override
protected void addFormatters(FormatterRegistry registry) {
this.configurers.addFormatters(registry);
}
//拦截器
@Override
protected void addInterceptors(InterceptorRegistry registry) {
this.configurers.addInterceptors(registry);
}
//添加资源映射
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
this.configurers.addResourceHandlers(registry);
}
//用来添加Cros跨域映射
@Override
protected void addCorsMappings(CorsRegistry registry) {
this.configurers.addCorsMappings(registry);
}
//给controller的映射适配资源文件,就和放在Template的html自动配置了解析一样
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
}
//增加视图解析器,就可我们配置的jsp的前缀后缀
@Override
protected void configureViewResolvers(ViewResolverRegistry registry) {
this.configurers.configureViewResolvers(registry);
}
//参数类型解析
@Override
protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
this.configurers.addArgumentResolvers(argumentResolvers);
}
@Override
protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
this.configurers.addReturnValueHandlers(returnValueHandlers);
}
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
this.configurers.configureMessageConverters(converters);
}
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
this.configurers.extendMessageConverters(converters);
}
@Override
protected void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
this.configurers.configureHandlerExceptionResolvers(exceptionResolvers);
}
@Override
protected void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
this.configurers.extendHandlerExceptionResolvers(exceptionResolvers);
}
@Override
@Nullable
protected Validator getValidator() {
return this.configurers.getValidator();
}
@Override
@Nullable
protected MessageCodesResolver getMessageCodesResolver() {
return this.configurers.getMessageCodesResolver();
}
}
进入资源配置后,对WebJars(就是对于一些前端的东西封装到Jar里面去了)的内容进行加载,如果没有的话就从resourceProperties中找
进入ResourceProperties中看看,可以看到定义了很多个classpath,这些都是资源文件加载的根目录
因此我们的资源文件写在这几个目录下就会被加载,因此我们又来回头看看为什么加了@EnableWebMvc就让它失效了呢?
可以看到对WebMvcConfigurationSupport的自动配置是在没有自定义WebMvcConfigurationSupport的前提下
那就顺藤摸瓜,看看WebMvcConfigurationSupport的子类都有些什么
很明显,和资源配置有关的除了自己就剩了DelegatingWebMvcConfiguration了,因此进入DelegatingWebMvcConfiguration,有没有感觉到眼熟呢?没错就是我们前面看间@EnableWebMvc中@import的一个class。
原因:所以原因就找到了,是因为配置了@EnableWebMvc,因此就相当于自定义了DelegatingWebMvcConfiguration,也就相当于实现了WebMvcConfigurationSupport,因此再配合上@ConditionOnMissing注解,理所当然的自动配置就消失了,因此资源文件就不能加载出来了。