springboot是如何实现自动装配的(三)静态资源配置源码

系列文章目录

springboot是如何实现自动装配的(一)注解分析
springboot是如何实现自动装配的(二)条件装配
springboot是如何实现自动装配的(三)静态资源配置源码



前言

前两章我们分析了springboot的自动装配原理和按需装配的实现,本章我们来继续分析一下springMVC静态资源配置的一些源码,带着三个问题分析一下静态资源的配置原理,

1.我们都知道,springboot的静态资源是可以放置在:
“classpath:/META-INF/resources/”,“classpath:/resources/”, “classpath:/static/”, “classpath:/public/” 这四个路径下的,放在这四个路径下的资源可以通过URL地址直接访问。
2.我们也可以通过在配置文件中指定
spring.mvc.static-path-pattern
这个配置来添加静态资源的访问前缀。
3.我们还可以通过在配置文件中指定spring.resources.staticLocations这个配置来修改静态资源路径。

那么带着这三个问题。我们分析源码。看看究竟是怎么回事


一、从何处入手

既然分析springMVC配置,我们先从springboot的自动配置类开始入手,也就是AutoConfiguration类。我们找到spring-boot-autoconfigure-2.3.0.RELEASE.jar包下的web子包,在子包中找到servlet子包,然后找到WebMvcAutoConfiguration.class这个配置类
在这里插入图片描述


开始分析

惯例看开头注释,但是什么也没写,就不看了。

生效条件

看类上的注解
在这里插入图片描述
从上到下
第一个注解声明了这是个配置类
第二注解要求这是个基于servlet的web应用
第三个注解说要存在 Servlet.class,DispatcherServlet.class, WebMvcConfigurer.class ,这三个类才能生效,对于我们来讲,只要导入了spring-boot-starter-web这个依赖就必然会存在
第四个注解说容器中要没有WebMvcConfigurationSupport.class这个配置类才生效,这个类目前肯定是没有的,这个类是可以自定义MVC的一些功能的,后期可以研究。
剩下两个一个排序,一个是配置条件,要在XX类之后初始化配置。
总是此配置文件是能够生效的。

做了什么

第一个bean,注解就不解释了 ,不明白的我上一篇文章里有讲可以去看。在这里插入图片描述
向容器注入一个类,干嘛用的呢,就是支持put/delete等请求方法的。我们看这个类的源码发现它继承了另一个类HiddenHttpMethodFilter,直接看这个类的注释。
在这里插入图片描述
说白了就是通过POST加一个隐藏域参数来模拟多种请求方法,来支持restful的设计模式。
下面这个bean是用来解析put /patch/delete请求的。
在这里插入图片描述
这些都不是我们关心的重点,我们关心的重点在下面这个内部类上

@Configuration(proxyBeanMethods = false)
	@Import(EnableWebMvcConfiguration.class)
	@EnableConfigurationProperties({
    
     WebMvcProperties.class, ResourceProperties.class })
	@Order(0)
	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    
    

第三个注解表明了,它和WebMvcProperties.class, ResourceProperties.class这连个配置类进行了绑定。
查看这两个类我们发现他们分别和配置文件前缀为spring.mvcspring.resources进行了绑定
在这里插入图片描述
在这里插入图片描述

也就是可以通过这两个前缀的相关属性来配置MVC的一些内容。
然后我们看构造方法,只有一个有参构造,说明什么?说明一切参数实例都要从容器中获取。

		public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties,
				ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider,
				ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) {
    
    
			this.resourceProperties = resourceProperties;
			this.mvcProperties = mvcProperties;
			this.beanFactory = beanFactory;
			this.messageConvertersProvider = messageConvertersProvider;
			this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
		}

所以到底干了些什么呢?
首先获取了ResourceProperties resourceProperties, WebMvcProperties mvcProperties两个类所绑定的值和对象,即配置文件中的配置。
然后第三个参数ListableBeanFactory beanFactory spring的beanFactory
第四个参数ObjectProvider messageConvertersProvider所有的HttpMessageConverters
第五个参数ObjectProvider resourceHandlerRegistrationCustomizerProvider 资源处理器的自定义器

构造方法讲完我们继续向下,找到资源相关的配置方法addResourceHandlers

		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
    
    
			if (!this.resourceProperties.isAddMappings()) {
    
    
				logger.debug("Default resource handling disabled");
				return;
			}
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
			if (!registry.hasMappingForPattern("/webjars/**")) {
    
    
				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
    
    
				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
						.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
		}

资源处理的默认规则都在上面了。详细分析一下

			if (!this.resourceProperties.isAddMappings()) {
    
    
				logger.debug("Default resource handling disabled");
				return;
			}

上面的if语句表示要获取resourceProperties配置类的isAddMappings属性,如果属性为tfalse就执行这个if语句,默认配置也就不生效了,因为默认配置在后面,没有办法得到执行。

			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
			if (!registry.hasMappingForPattern("/webjars/**")) {
    
    
				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}

上面这段干啥了呢,获取了你配置的缓存的时间,将匹配的“/webjars/**”路径添加到"classpath:/META-INF/resources/webjars/"下面,就是个地址转换。
然后设置缓存,.setCachePeriod缓存时间就是获取的你配置的缓存时间。

			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
    
    
				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
						.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}

然后又从WebMvcProperties这个配置类中获取StaticPathPattern这个属性,这就是个静态资源路径,因为绑定了配置文件,所以可以在配置文件中设置。
在这里插入图片描述
通过查看WebMvcProperties类的源码我们知道,这个属性是有默认值的“/”,同时解释了我们的第二个问题,访问前缀的设置。
在这里插入图片描述
假定我们没有配置这个属性,那么跟着源码往下走,就会看到它将“/**”的这个路径映射到了resourceProperties这个配置类的StaticLocations属性下,跟进源码看看这下面都有啥?
在这里插入图片描述
上图1处我们看到他是个String数组并且指向一个常量,常量在上图2的位置,即4个路径。
由此。我总结上面的源代码,就是将“/**”即全部请求不路径映射到上面的四个资源路径上。
自此完结。解释了资源路径是怎么映射到
==“classpath:/META-INF/resources/”,“classpath:/resources/”, “classpath:/static/”,“classpath:/public/” ==这四个静态资源路径上的。
这同时解决了我们的第一个问题
为什么是这四个路径和第三个问题静态资源路径的设置**


总结

通过源码分析。我们知道了springboot静态资源路径的配置是怎么一回事儿。所以源码还是要读的。我也是一边学习一边写这些东西。有不对的地方还请大神们多多指点。

猜你喜欢

转载自blog.csdn.net/qq_31277409/article/details/114752460
今日推荐