springboot2版本無(wú)法加載靜態(tài)資源問(wèn)題解決
前言
在學(xué)習(xí)springboot的過(guò)程中,發(fā)現(xiàn)無(wú)法引用靜態(tài)資源。我使用的是springboot2.2.1版本。
追溯源碼,終于解決。并記錄下解決思路。
默認(rèn)加載路徑
首先得知道springboot默認(rèn)加載得資源路徑是什么。
首先我們看WebMvcAutoConfiguration這個(gè)類。里面有一個(gè)方法叫做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會(huì)將我們classpath:/META-INF/resources/webjars/路徑下的文件映射為/webjars/**
然后再一個(gè)if判斷進(jìn)行靜態(tài)資源文件夾映射,首先判斷我們是否以使用 "/**" 做映射
如果沒(méi)有,則將"/**" 訪問(wèn)當(dāng)前項(xiàng)目的任何資源,都去(如下靜態(tài)資源的文件夾)找映射
"classpath:/META‐INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" "/":當(dāng)前項(xiàng)目的根路徑
什么意思呢?舉一個(gè)例子,就是說(shuō)默認(rèn)情況下我們假如我們調(diào)用 http://localhost:8080/a.json
Springboot就會(huì)從上面得這幾個(gè)路徑下去找a.json這個(gè)文件。
問(wèn)題所在
源碼也是如同猜想得這樣,那為什么我的代碼中,直接訪問(wèn)靜態(tài)資源卻無(wú)法做映射呢?
我們?cè)僮屑?xì)看看WebMvcAutoConfiguration這個(gè)類。在其頭上有一個(gè)這個(gè)注解:
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
臥槽,瞬間恍然大悟。在我得配置文件中:
@Configuration public class MyMVCConfig extends WebMvcConfigurationSupport{ ... }
繼承了WebMvcConfigurationSupport這個(gè)類,使得springboot的自動(dòng)裝配失效了。因?yàn)锧ConditionalOnMissingBean這個(gè)注解得作用就是,當(dāng)容器中不存在這個(gè)類,如下得代碼才有作用。
為什么會(huì)這樣設(shè)計(jì)呢?
因?yàn)橛袝r(shí)候我們得項(xiàng)目并不希望springboot給我們自動(dòng)裝配。希望完全由我們自己來(lái)配置自己來(lái)掌握。
要想達(dá)到這個(gè)效果,springboot給我們提供了一個(gè)更為簡(jiǎn)潔得方式。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
@EnableWebMvc注解會(huì)導(dǎo)入DelegatingWebMvcConfiguration.clss
而DelegatingWebMvcConfiguration又繼承了WebMvcConfigurationSupport
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
所以當(dāng)我們加上@EnableWebMvc也會(huì)有同樣得效果且簡(jiǎn)潔。
自定義配置資源映射
springboot當(dāng)然也支持我們個(gè)性化得指定映射路徑,我總結(jié)了如下幾個(gè)方式:
配置類
@Configuration public class MyMVCConfig extends WebMvcConfigurationSupport{ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } }
上面的意思就是:將所有/static下得文件全部映射到/static/**
配置項(xiàng)
在application.properties文件中加上如下配置項(xiàng)
spring.mvc.static-path-pattern=/** spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/, classpath:/static/,classpath:/public/
spring.mvc.static-path-pattern=/**:表示所有的訪問(wèn)都經(jīng)過(guò)靜態(tài)資源路徑;
spring.resources.static-locations:在這里配置靜態(tài)資源路徑。
相關(guān)文章
詳解SpringBoot緩存的實(shí)例代碼(EhCache 2.x 篇)
這篇文章主要介紹了詳解SpringBoot緩存的實(shí)例代碼(EhCache 2.x 篇),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07java中應(yīng)用Stack進(jìn)行算術(shù)運(yùn)算的操作
這篇文章主要介紹了java中應(yīng)用Stack進(jìn)行算術(shù)運(yùn)算的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03Java struts2 package元素配置及實(shí)例解析
這篇文章主要介紹了Java struts2 package元素配置及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11Java每7天日志自動(dòng)清理的項(xiàng)目實(shí)踐
在實(shí)際項(xiàng)目中由于服務(wù)器內(nèi)存有限,人工清理常會(huì)忘記,本文主要介紹了Java每7天日志自動(dòng)清理的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Java字符串拼接+和StringBuilder的比較與選擇
Java 提供了兩種主要的方式:使用 "+" 運(yùn)算符和使用 StringBuilder 類,本文主要介紹了Java字符串拼接+和StringBuilder的比較與選擇,感興趣的可以了解一下2023-10-10MyBatisPlus+SpringBoot實(shí)現(xiàn)樂(lè)觀鎖功能詳細(xì)流程
樂(lè)觀鎖是針對(duì)一些特定問(wèn)題的解決方案,主要解決丟失更新問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于MyBatisPlus+SpringBoot實(shí)現(xiàn)樂(lè)觀鎖功能的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03