springboot2版本無法加載靜態(tài)資源問題解決
前言
在學習springboot的過程中,發(fā)現(xiàn)無法引用靜態(tài)資源。我使用的是springboot2.2.1版本。
追溯源碼,終于解決。并記錄下解決思路。
默認加載路徑
首先得知道springboot默認加載得資源路徑是什么。
首先我們看WebMvcAutoConfiguration這個類。里面有一個方法叫做addResourceHandlers()
@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 {
@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();
//所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找資源
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
//靜態(tài)資源文件夾映射
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
首先springboot會將我們classpath:/META-INF/resources/webjars/路徑下的文件映射為/webjars/**
然后再一個if判斷進行靜態(tài)資源文件夾映射,首先判斷我們是否以使用 "/**" 做映射
如果沒有,則將"/**" 訪問當前項目的任何資源,都去(如下靜態(tài)資源的文件夾)找映射
"classpath:/META‐INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" "/":當前項目的根路徑
什么意思呢?舉一個例子,就是說默認情況下我們假如我們調用 http://localhost:8080/a.json
Springboot就會從上面得這幾個路徑下去找a.json這個文件。
問題所在
源碼也是如同猜想得這樣,那為什么我的代碼中,直接訪問靜態(tài)資源卻無法做映射呢?
我們再仔細看看WebMvcAutoConfiguration這個類。在其頭上有一個這個注解:
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
臥槽,瞬間恍然大悟。在我得配置文件中:
@Configuration
public class MyMVCConfig extends WebMvcConfigurationSupport{
...
}
繼承了WebMvcConfigurationSupport這個類,使得springboot的自動裝配失效了。因為@ConditionalOnMissingBean這個注解得作用就是,當容器中不存在這個類,如下得代碼才有作用。
為什么會這樣設計呢?
因為有時候我們得項目并不希望springboot給我們自動裝配。希望完全由我們自己來配置自己來掌握。
要想達到這個效果,springboot給我們提供了一個更為簡潔得方式。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
@EnableWebMvc注解會導入DelegatingWebMvcConfiguration.clss
而DelegatingWebMvcConfiguration又繼承了WebMvcConfigurationSupport
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
所以當我們加上@EnableWebMvc也會有同樣得效果且簡潔。
自定義配置資源映射
springboot當然也支持我們個性化得指定映射路徑,我總結了如下幾個方式:
配置類
@Configuration
public class MyMVCConfig extends WebMvcConfigurationSupport{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
上面的意思就是:將所有/static下得文件全部映射到/static/**
配置項
在application.properties文件中加上如下配置項
spring.mvc.static-path-pattern=/** spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/,classpath:/public/
spring.mvc.static-path-pattern=/**:表示所有的訪問都經(jīng)過靜態(tài)資源路徑;
spring.resources.static-locations:在這里配置靜態(tài)資源路徑。
相關文章
詳解SpringBoot緩存的實例代碼(EhCache 2.x 篇)
這篇文章主要介紹了詳解SpringBoot緩存的實例代碼(EhCache 2.x 篇),具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
Java字符串拼接+和StringBuilder的比較與選擇
Java 提供了兩種主要的方式:使用 "+" 運算符和使用 StringBuilder 類,本文主要介紹了Java字符串拼接+和StringBuilder的比較與選擇,感興趣的可以了解一下2023-10-10
MyBatisPlus+SpringBoot實現(xiàn)樂觀鎖功能詳細流程
樂觀鎖是針對一些特定問題的解決方案,主要解決丟失更新問題,下面這篇文章主要給大家介紹了關于MyBatisPlus+SpringBoot實現(xiàn)樂觀鎖功能的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2023-03-03

