前言
WebMvcAutoConfiguration
中有一些常用的与静态资源相关的配置项,本文回顾一下其中原理。本文中SpringBoot版本号为2.7.5。
原文地址:https://xuedongyun.cn/post/3386/
静态资源配置原理
WebMvcAutoConfiguration
SpringBoot启动会自动加载WebMvcAutoConfiguration
类。(具体原因可以查看我之前的博客:SpringBootApplication注解背后的原理),我们首先看看这个自动配置类生效的条件:
// 代码有删减
@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class,
TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
// 典型的Web Servlet应用才生效
@ConditionalOnWebApplication(type = Type.SERVLET)
// 导了SpringMVC有这些类,生效
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// 如果容器中有WebMvcConfigurationSupport类,会全面接管SpringMVC
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
public class WebMvcAutoConfiguration {
}
WebMvcAutoConfigurationAdapter
WebMvcAutoConfiguration
类中,还有一个静态类WebMvcAutoConfigurationAdapter
。它还绑定了两个属性类WebMvcProperties
和WebProperties
,我们可以在配置文件中更改相应配置项的属性,实现对某些功能的自定义
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, WebProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {}
@ConfigurationProperties("spring.web")
public class WebProperties {}
WebMvcAutoConfigurationAdapter
只有一个构造函数,所有值从容器中获取
public WebMvcAutoConfigurationAdapter(
// 两个属性类
WebProperties webProperties,
WebMvcProperties mvcProperties,
// Spring的IOC容器
ListableBeanFactory beanFactory,
// 所有的messageConverter,此处不涉及
ObjectProvider<HttpMessageConverters> messageConvertersProvider,
// 所有的资源自定义器,重点
ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider,
// DispathcerServlet能处理的所有路径,此处不涉及
ObjectProvider<DispatcherServletPath> dispatcherServletPath,
// 应用注册的原生Servlet,Filter...此处不涉及
ObjectProvider<ServletRegistrationBean<?>> servletRegistrations
) {
this.resourceProperties = webProperties.getResources();
this.mvcProperties = mvcProperties;
}
在WebMvcAutoConfigurationAdapter
类中,有一些与资源相关的核心方法
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/*
可以禁用资源的路径映射,所有静态资源都无法访问
spring.web.resources.add-mappings = false
*/
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
/*
所有/webjars/**的静态资源,都会去classpath:/META-INF/resources/webjars/找
*/
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
/*
staticPathPattern 默认值"/**"
staticLocations 默认值 { "classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/" }
所有静态资源请求都会去对应路径找
*/
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource =
new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
});
}
// 代码有删减
private void addResourceHandler(ResourceHandlerRegistry registry, String pattern,
Consumer<ResourceHandlerRegistration> customizer) {
...
// 比如:可以通过spring.web.cache.period控制缓存的时间
registration.setCachePeriod(getSeconds(this.resourceProperties.getCache().getPeriod()));
registration.setCacheControl(this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl());
registration.setUseLastModified(this.resourceProperties.getCache().isUseLastModified());
...
}
前面提到的配置项
spring:
web:
resources:
add-mappings: false # 关闭静态资源的访问
static-locations: [classpath:/haha/, classpath:/page/] # 静态资源存放路径
cache:
period: 3600 # 静态资源缓存时间(秒)
mvc:
static-path-pattern: /resources/** # 改变静态资源访问路径(便于拦截器放行静态资源)