经过我们分析springboot的自动装配原理之后,我们知道了,再springboot 一启动,就会注册我们导入依赖的场景中的所有组件。
我们要分析静态资源的配置原理,那么我们需要去看关于资源配置的自动配置类,我们直接找到springMVC的自动配置类
位于org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
springmvc的自动配置类就集中在这个类,但是整个完整的springMVC功能需要和其他的web场景下的自动配置类一起实现。这个配置类是核心配置类
我们查看这个配置为什么会自动生效
很显然,是满足这三个条件的,所以才会执行下面的这些代码
我们接下来看当这个类生效了之后,执行的代码
它里面注册了很多组件,还有几个内部类
我们看这个内部类
看到@Configuration(proxyBeanMethods = false)
注解我们知道了,当前的内部类是一个配置类,并在再容器中注册了这个配置类的组件,并且是轻量级的配置。
根据@EnableConfigurationProperties
这个注解我们知道了,它进行了配置绑定,我们跟入查看这些配置的绑定参数
第一个参数WebMvcProperties.class的绑定前缀为spring.mvc
第二个参数org.springframework.boot.autoconfigure.web.ResourceProperties.class的绑定前缀为spring.resources
第三个参数WebProperties.class的绑定前缀为spring.web
然后接观察发现,我们的当前这个配置类只有一个有参构造器
根据配置类的注入原理,当前类只有一个有参构造器时,那么这个有参构造的参数会默认从容器中获取。
然后我们来看这个有参构造需要从容器中都获取哪些参数
- WebProperties webProperties:这个参数就是我们上面的那个内部类使用
@EnableConfigurationProperties
注解再容器中注册了,所以一定可以获取到。也能够获取到spring.mvc为前缀的配置信息 - WebMvcProperties mvcProperties:这个参数同样使用
@EnableConfigurationProperties
注解再容器中注册了,它能够获取spring.web为前缀的配置信息 - ListableBeanFactory beanFactory:这个相当于找我们的spring容器,就是我们的bean工厂
ObjectProvider<HttpMessageConverters> messageConvertersProvider
:找到所有HttpMessageConvertersObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider
:找到资源处理器的自定义器ObjectProvider<DispatcherServletPath> dispatcherServletPath
:找到处理的路径ObjectProvider<ServletRegistrationBean<?>> servletRegistrations
:给应用注册原生的servlet、Filter、Listoner。。。后面再说
按照老师的讲课版本,这个内部类中应该包含一个addResourceHandlers方法,但是我的这个版本是
2.4.3这个版本的。我的这个方法再另一个叫做EnableWebMvcConfiguration的内部类当中
这个内部类也是一个配置类,并且绑定了配置信息,这个绑定的配置信息的前缀为spring.web
我们来看这个内部类中的addResourceHandlers方法
这个方法就是所有资源处理的默认规则
我们一点一点看
首先是resourceProperties.isAddMappings()
这个resourceProperties就是我们的Resource
这个resource就是我们的WebPropertes类中的一个内部类。
跟进查看
我们发现有一个私有的addMapping
然后我们跟进到isAddMapping这个方法
这个方法就是返回的这个私有的addMapping,默认是true。
也就是说这个判断条件是false
所以它就会不走这个而直接走下面的代码。
这也就意味着我们如果返回是一个false的话,就禁用了默认的静态资源处理方式
我们看到WebProperties这个类中的内类Resource的这个addMapping属性有一个set方法,
那么就意味着我们可以通过配置绑定来设置这个addMapping的值
举例示范禁用默认的静态资源处理方式:
先展示不禁用:
成功访问到静态资源
然后测试禁用默认的静态资源处理方式
application.yaml
访问失败,说明禁用成功
然后我们来回过头来看它默认的静态资源处理方式是什么
它有这两种的默认处理方式
第一种的访问规则注册的是/webjars/**,这个就是我们的jar版本的jquery的那种静态文件的访问规则,可以看到它匹配的路径就是类路径下的我们这个路径classpath:/META-INF/resources/webjars/
,
然后我们观察第二种的默认注册方式
默认的访问路径是它this.mvcProperties.getStaticPathPattern()
,我们跟入getStaticPathPattern这个方法
然后跟入返回的这个staticPathPattern这个属性
发现就是/**,正如注释解释的这个是访问静态资源的目录。
然后我们接着看它默认是去哪里找的这个资源,也就是这个第三个参数
这里使用了lambda的写法,不用在意,
我们跟入下面这个方法查看得到的是什么
首先进入了getLocation方法
然后再跟入staticLocations这个属性
然后跟入到这个字符串数组
发现返回的就是这个数组数组内容分别是
- “classpath:/META-INF/resources/”
- “classpath:/resources/”
- “classpath:/static/”
- “classpath:/public/”
这就是最终获取静态资源的默认路径,正是这四个包
这样静态资源的默认访问规则的原理就大致说清了。
下面的是欢迎页的源码分析
再核心的web自动配置类(WebMvcAutoConfiguration)中有这样一个方法
注册了欢迎页的组件
我们再了解这个欢迎页的源码原理之前需要回顾一个知识点
HanderMapping是什么?
HanderMapping是处理器映射,保存了每一个Handler能处理的请求
我们来看这个参数
这个参数就是默认欢迎页访问的路径
我们跟入查看
WebMvcProperties这个类的getStaticPathPattern方法
这个方法返回的就是默认路径
这个默认路径就是/**。
然后我们看它寻找欢迎页的路径是哪里,这个是该方法的第三个参数设置的
跟进到这个方法查看,源码如下
循环的这个String类型的数组就是我们前面说的那个默认静态资源的数组路径,就是下面这个路径
循环这个stirng类型的数组依次传入到getIndexHtml(location)这个方法中。
我们接着来看这个方法是做什么的
然后我们看这个重载方法是做什么的
如果这个欢迎页存在的话就会返回回来
然后这个方法经过传入参数返回一个WelcomePageHandlerMapping类型的数据
这个类中就设置了视图名字。。。。。大概这个意思把,这个欢迎页的源码分析可能有些问题