一、說在前面的話
我們之間介紹過SpringBoot自動配置的原理,基本上是如下:
1
2
|
xxxxAutoConfiguration:幫我們給容器中自動配置組件; xxxxProperties:配置類來封裝配置文件的內容; |
二、靜態資源映射規則
1、對哪些目錄映射?
1
2
3
4
5
|
classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ /:當前項目的根路徑 |
2、什么意思?
就我們在上面五個目錄下放靜態資源(比如:a.js等),可以直接訪問(http://localhost:8080/a.js),類似于以前web項目的webapp下;放到其他目錄下無法被訪問。
3、為什么是那幾個目錄?
3.1、看源碼
我們一起來讀下源碼,這個是SpringBoot自動配置的WebMvcAutoConfiguration.java
類來幫我們干的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (! this .resourceProperties.isAddMappings()) { logger.debug( "Default resource handling disabled" ); return ; } Integer cachePeriod = this .resourceProperties.getCachePeriod(); if (!registry.hasMappingForPattern( "/webjars/**" )) { customizeResourceHandlerRegistration( registry.addResourceHandler( "/webjars/**" ) .addResourceLocations( "classpath:/META-INF/resources/webjars/" ) .setCachePeriod(cachePeriod)); } String staticPathPattern = this .mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this .resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } } |
3.2、分析源碼
我們重點分析后半截,前半截后面會介紹。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// staticPathPattern是/** String staticPathPattern = this .mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this .resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } this .resourceProperties.getStaticLocations() ========> ResourceProperties public String[] getStaticLocations() { return this .staticLocations; } ========> private String[] staticLocations = RESOURCE_LOCATIONS; ========> private static final String[] RESOURCE_LOCATIONS; private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/" , "classpath:/resources/" , "classpath:/static/" , "classpath:/public/" }; ========> static { // 可以看到如下是對上面兩個數組進行復制操作到一個新數組上,也就是合并。 RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length + SERVLET_RESOURCE_LOCATIONS.length]; System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0 , RESOURCE_LOCATIONS, 0 , SERVLET_RESOURCE_LOCATIONS.length); System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0 , RESOURCE_LOCATIONS, SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length); } 所以上述代碼經過我的翻譯后成為了如下樣子: registry.addResourceHandler( "/**" ).addResourceLocations( "classpath:/META-INF/resources/" , "classpath:/resources/" , "classpath:/static/" , "classpath:/public/" , "/" ) // 設置緩存時間 .setCachePeriod(cachePeriod)); |
3.3、一句話概括
WebMvcAutoConfiguration
類自動為我們注冊了如下目錄為靜態資源目錄,也就是說直接可訪問到資源的目錄。
1
2
3
4
5
|
classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ /:當前項目的根路徑 |
優先級從上到下。
所以,如果static里面有個index.html,public下面也有個index.html,則優先會加載static下面的index.html,因為優先級!
4、默認首頁
PS:就是直接輸入ip:port/項目名稱默認進入的頁面。
4.1、看源碼
1
2
3
4
5
6
7
8
|
WebMvcAutoConfiguration.java @Bean public WelcomePageHandlerMapping welcomePageHandlerMapping( ResourceProperties resourceProperties) { return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(), this .mvcProperties.getStaticPathPattern()); } |
4.2、分析源碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
resourceProperties.getWelcomePage() ========> public Resource getWelcomePage() { // 遍歷默認靜態資源目錄后面拼接個index.html的數組 // 比如:[/static/index.html, /public/index.html等等] for (String location : getStaticWelcomePageLocations()) { Resource resource = this .resourceLoader.getResource(location); try { if (resource.exists()) { resource.getURL(); return resource; } } catch (Exception ex) { // Ignore } } return null ; } ========> // 下面這段代碼通俗易懂,就是給默認靜態資源目錄后面拼接個index.html并返回,比如:/static/index.html private String[] getStaticWelcomePageLocations() { String[] result = new String[ this .staticLocations.length]; for ( int i = 0 ; i < result.length; i++) { String location = this .staticLocations[i]; if (!location.endsWith( "/" )) { location = location + "/" ; } result[i] = location + "index.html" ; } return result; } |
所以上述代碼經過我的翻譯后成為了如下樣子:
1
2
3
4
5
6
7
|
return new WelcomePageHandlerMapping( "classpath:/META-INF/resources/index.html" , "classpath:/resources/index.html" , "classpath:/static/index.html" , "classpath:/public/index.html" , "/index.html" , "/**" ); |
4.3、一句話概括
WebMvcAutoConfiguration
類自動為我們注冊了如下文件為默認首頁。
1
2
3
4
5
|
classpath:/META-INF/resources/index.html classpath:/resources/index.html classpath:/static/index.html classpath:/public/index.html /index.html |
優先級從上到下。
所以,如果static里面有個index.html,public下面也有個index.html,則優先會加載static下面的index.html,因為優先級!
5、favicon.ico
PS:就是這個圖標。
5.1、看源碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
@Configuration @ConditionalOnProperty (value = "spring.mvc.favicon.enabled" , matchIfMissing = true ) public static class FaviconConfiguration { private final ResourceProperties resourceProperties; public FaviconConfiguration(ResourceProperties resourceProperties) { this .resourceProperties = resourceProperties; } @Bean public SimpleUrlHandlerMapping faviconHandlerMapping() { SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1 ); mapping.setUrlMap(Collections.singletonMap( "**/favicon.ico" , faviconRequestHandler())); return mapping; } @Bean public ResourceHttpRequestHandler faviconRequestHandler() { ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); requestHandler .setLocations( this .resourceProperties.getFaviconLocations()); return requestHandler; } } |
5.2、分析源碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// 首先可以看到的是可以設置是否生效,通過參數spring.mvc.favicon.enabled來配置,若無此參數,則默認是生效的。 @ConditionalOnProperty (value = "spring.mvc.favicon.enabled" , matchIfMissing = true ) ========》 // 可以看到所有的**/favicon.ico都是在faviconRequestHandler()這個方法里找。 mapping.setUrlMap(Collections.singletonMap( "**/favicon.ico" , faviconRequestHandler())); ========》 faviconRequestHandler(). this .resourceProperties.getFaviconLocations() // 就是之前的五個靜態資源文件夾。 List<Resource> getFaviconLocations() { List<Resource> locations = new ArrayList<Resource>( this .staticLocations.length + 1 ); if ( this .resourceLoader != null ) { for (String location : this .staticLocations) { locations.add( this .resourceLoader.getResource(location)); } } locations.add( new ClassPathResource( "/" )); return Collections.unmodifiableList(locations); } |
5.3、一句話概括
只要把favicon.ico放到如下目錄下,就會自動生效。
1
2
3
4
5
|
classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/ /:當前項目的根路徑 |
6、webjars
6.1、看源碼
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
WebMvcAutoConfiguration @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (! this .resourceProperties.isAddMappings()) { logger.debug( "Default resource handling disabled" ); return ; } Integer cachePeriod = this .resourceProperties.getCachePeriod(); if (!registry.hasMappingForPattern( "/webjars/**" )) { customizeResourceHandlerRegistration( registry.addResourceHandler( "/webjars/**" ) .addResourceLocations( "classpath:/META-INF/resources/webjars/" ) .setCachePeriod(cachePeriod)); } String staticPathPattern = this .mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this .resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } } |
6.2、分析源碼
這次我們來分析前半截。
1
2
3
4
5
6
7
8
|
Integer cachePeriod = this .resourceProperties.getCachePeriod(); if (!registry.hasMappingForPattern( "/webjars/**" )) { customizeResourceHandlerRegistration( registry.addResourceHandler( "/webjars/**" ) .addResourceLocations( "classpath:/META-INF/resources/webjars/" ) .setCachePeriod(cachePeriod)); } |
6.3、一句話概括
所有/webjars/**
都從classpath:/META-INF/resources/webjars/
路徑下去找對應的靜態資源。
6.4、什么是webjars?
就是以jar包的方式引入靜態資源。
官網地址:http://www.webjars.org/。類似于maven倉庫。
我們可以做個例子,將jquery引入到項目中
1
2
3
4
5
|
< dependency > < groupId >org.webjars</ groupId > < artifactId >jquery</ artifactId > < version >3.3.1</ version > </ dependency > |
看項目依賴
會自動為我們引入jquery,要怎么使用呢?我們上面說過:
所有/webjars/*
都從classpath:/META-INF/resources/webjars/
路徑下去找對應的靜態資源。
所以我們啟動項目,訪問:http://localhost:8080/webjars/jquery/3.3.1/jquery.js即可。
必須在這幾個路徑下SpringBoot才會掃描到!
"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/"
"/":當前項目的根路徑
到此這篇關于SpringBoot中的靜態資源訪問的實現的文章就介紹到這了,更多相關SpringBoot 靜態資源訪問內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://www.cnblogs.com/gu-bin/p/11129066.html