SpringBoot静态资源加载原理

SpringBoot静态资源加载原理

之前的文章,我们说过,SpringBoot启动时会默认加载各种xxxAutoConfiguration 类,即自动配置类。

  • 静态资源的加载原理

SpringMVC功能的可以查看源码的 WebMvcAutoConfiguration类。

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
		ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {

从源码中,我们可以看出在满足

  1. @ConditionalOnWebApplication(type = Type.SERVLET) 是webapp
  2. @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })容器中有Servlet、DispatcherServlet、WebMvcConfigurer 三个类
  3. @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 容器中没有WebMvcConfigurationSupport 类
    满足以上条件时,该配置类会生效

其中该类中一个重要的内部配置类是静态资源加载原理的核心

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

其中 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })将该类和WebMvcProperties与ResourceProperties关联的配置文件相关联,我们可以查看这两个类的源码

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {

此时我们可以看出WebMvcProperties类与配置文件中以spring.mvc为前缀的配置相关联,而ResourceProperties类则与配置文件中以spring.resources为签注爹配置相关联
我们知道spring.resources.static-locations 是配置spring静态资源目录的一个配置属性。这时候我们就可以去查看ResourceProperties类的源码

	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
			"classpath:/resources/", "classpath:/static/", "classpath:/public/" };

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/].
	 */
	private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;

这里就体现了spring默认配置的静态资源路径是"classpath:/META-INF/resources/",
“classpath:/resources/”, “classpath:/static/”, “classpath:/public/”
我们可以直接将静态资源文件放在这几个目录中,就可以直接访问。


  • WebMvcAutoConfigurationAdapter

该类是spring静态资源默认加载的一个重要配置类,该类又一个构造方法

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

该构造函数所有参数的值都会从容器中确定
ResourceProperties resourceProperties 获取和spring.resources绑定的所有的值的对象【ResourceProperties.class】
WebMvcProperties mvcProperties 获取和spring.mvc绑定的所有的值的对象【WebMvcProperties.class】
ListableBeanFactory beanFactory 是Spring的beanFactory
HttpMessageConverters 找到所有的HttpMessageConverters
ResourceHandlerRegistrationCustomizer 找到 资源处理器的自定义器

有时我们会添加spring.mvc.static-path-pattern属性来给访问路径添加前缀
首先我们看到他是spring.mvc开头的属性,所以与WebMvcProperties类有关

	private String staticPathPattern = "/**";

我们在这个类中果然找到了该配置项默认的路径

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

而他又在WebMvcAutoConfigurationAdapter中的addResourceHandlers方法进行判断


  • 欢迎页的处理规则

我们将名为index.html的文件放在默认静态资源目录下,在项目启动后则会默认访问欢迎页,该配置依旧在WebMvcAutoConfiguration类中可以找到相关配置

		@Bean
		public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext,
				FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
			WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(
					new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(),
					this.mvcProperties.getStaticPathPattern());
			welcomePageHandlerMapping.setInterceptors(getInterceptors(mvcConversionService, mvcResourceUrlProvider));
			welcomePageHandlerMapping.setCorsConfigurations(getCorsConfigurations());
			return welcomePageHandlerMapping;
		}

其中的welcomePageHandlerMapping是该配置的核心。

	WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
			ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
		if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
			logger.info("Adding welcome page: " + welcomePage.get());
			setRootViewName("forward:index.html");
		}
		else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
			logger.info("Adding welcome page template: index");
			setRootViewName("index");
		}
	}

这块代码的可读性很强
当if (welcomePage.isPresent() && “/**”.equals(staticPathPattern)) {该条件成立时,即可转发请求至index.html 即欢迎页存在且staticPathPattern为 “/**”
其中staticPathPattern在上面我们说过,是一个配置项,与WebMvcProperties类相关联


以上就是关于SpringBoot静态资源加载的相关原理。
其主要代码旧在WebMvcAutoConfiguration类中,该类也是SpringMVC的重要自动配置类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值