通過idea快速搭建一個springboot項目:
springboot版本2.1.6
在網上看的資料,springboot靜態資源訪問如下:
"classpath:/META‐INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"
"/":當前項目的根路徑
之后在測試訪問靜態資源的時候沒有問題,通過代碼配置的方式訪問登錄頁面資源的時候出現了404。
在網上找了很多關於靜態資源訪問404的問題,貌似不是在application.yml(或properties)中配置訪問路徑,就是自己定義config類。
后來翻看源碼發現,由於在代碼配置的時候。繼承了WebMvcConfigurationSupport這個類,導致整個資源訪問失效,具體原因如下:
第一步:
確認springboot靜態資源訪問的位置,由於springboot自動加載配置,所以找到WebMvcAutoConfiguration這個配置類,里面有很多方法,
只需找到資源映射的方法:
public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); } else { Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
<!-- /webjars/** 訪問的,資源映射規則-->
if (!registry.hasMappingForPattern("/webjars/**")) { this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).
addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); } <!-- 靜態資源映射規則--> String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).
addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())).
setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl)); } } }
第一種webjars加載:所有 /webjars/** ,都去 classpath:/META-INF/resources/webjars/ 找資源;
第二種靜態資源映射:
staticPathPattern 點擊查看源碼:staticPathPattern = /**;
resourceProperties.getStaticLocations() 點擊查看源碼:
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"}; private String[] staticLocations; private boolean addMappings; private final ResourceProperties.Chain chain; private final ResourceProperties.Cache cache; public ResourceProperties() { this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS; this.addMappings = true; this.chain = new ResourceProperties.Chain(); this.cache = new ResourceProperties.Cache(); } public String[] getStaticLocations() { return this.staticLocations; }
通過以上源碼看出,訪問資源路徑跟一開始測試時的一樣,沒問題,為何通過配置設置登錄頁面就無法訪問靜態資源了呢,反復查看WebMvcAutoConfiguration源碼發現如下:
@Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) @ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) @AutoConfigureOrder(-2147483638) @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class}) public class WebMvcAutoConfiguration {=
@ConditionalOnClass 和 @ConditionalOnMissingBean 這兩個注解的條件成立WebMvcAutoConfiguration才會自動加載,
在配置登錄頁的時候,正好繼承了WebMvcConfigurationSupport類
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class}) 容器沒有加載這個bean時自動加載WebMvcAutoConfiguration,
繼承WebMvcAutoConfiguration的方式也可以,不過需要手動添加資源映射路徑,WebMvcAutoConfiguration中的其他自動加載項也需要自己處理。
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class}) 容器加載這個bean時自動加載WebMvcAutoConfiguration
重新修改配置類 實現WebMvcConfigurer接口對登錄頁進行處理,靜態資源訪問正常。
