SpringWeb項目除了我們常見的傳回json串之外,還可以直接傳回靜态資源(當然在現如今前後端分離比較普遍的情況下,不太常見了),一些簡單的web項目中,前後端可能就一個人包圓了,前端頁面,js/css檔案也都直接放在Spring項目中,那麼你知道這些靜态資源檔案放哪裡麼
<!-- more -->
I. 預設配置
1. 配置
靜态資源路徑,SpringBoot預設從屬性
spring.resources.static-locations
中擷取
預設值可以從
org.springframework.boot.autoconfigure.web.ResourceProperties#CLASSPATH_RESOURCE_LOCATIONS
擷取
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
/**
* Locations of static resources. Defaults to classpath:[/META-INF/resources/,
* /resources/, /static/, /public/].
*/
private String[] staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
複制
注意上面的預設值,預設有四個,優先級從高到低
-
/META-INF/resources/
-
/resources/
-
/static/
-
/public/
2. 執行個體示範
預設靜态資源路徑有四個,是以我們設計case需要依次通路這四個路徑中的靜态資源,看是否正常通路到;其次就是需要判定優先級的問題,是否和上面說的一緻
首先建立一個SpringBoot web項目,工程建立流程不額外多說,pom中主要確定有下面依賴即可(本文使用版本為:
2.2.1.RELEASE
)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
複制
在資源檔案夾
resources
下,建立四個目錄,并添加html檔案,用于測試是否可以通路到對應的資源檔案(主要關注下圖中标紅的幾個檔案)
a. META-INF/resources
靜态檔案 m.html
<html>
<title>META-INF/resource/m.html</title>
<body>
jar包内,META-INF/resources目錄下 m.html
</body>
</html>
複制
完成對應的Rest接口
@GetMapping(path = "m")
public String m() {
return "m.html";
}
複制
b. resources
靜态檔案 r.html
<html>
<title>resources/r.html</title>
<body>
jar包内,resouces目錄下 r.html
</body>
</html>
複制
對應的Rest接口
@GetMapping(path = "r")
public String r() {
return "r.html";
}
複制
c. static
靜态檔案 s.html
<html>
<title>static/s.html</title>
<body>
jar包内,static目錄下 s.html
</body>
</html>
複制
對應的Rest接口
@GetMapping(path = "s")
public String s() {
return "s.html";
}
複制
d. public
靜态檔案 p.html
<html>
<title>public/p.html</title>
<body>
jar包内,public目錄下 p.html
</body>
</html>
複制
對應的Rest接口
@GetMapping(path = "p")
public String p() {
return "p.html";
}
複制
e. 優先級測試
關于優先級的測試用例,主要思路就是在上面四個不同的檔案夾下面放相同檔案名的靜态資源,然後根據通路時具體的傳回來确定相應的優先級。相關代碼可以在文末的源碼中擷取,這裡就不贅述了
II. 自定義資源路徑
一般來講,我們的靜态資源放在上面的四個預設檔案夾下面已經足夠,但總會有特殊情況,如果資源檔案放在其他的目錄下,應該怎麼辦?
1. 修改配置檔案
第一種方式比較簡單和實用,修改上面的
spring.resources.static-locations
配置,添加上自定義的資源目錄,如在
application.yml
中,指定配置
spring:
resources:
static-locations: classpath:/out/,classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
複制
上面指定了可以掃描
/out
目錄下的靜态資源檔案,且它的優先級是最高的(上面的配置順序中,優先級的高低從左到右)
執行個體示範
在資源目錄下,建立檔案
/out/index.html
請注意在其他的四個資源目錄下,也都存在
index.html
這個檔案(根據上面優先級的描述,傳回的應該是
/out/index.html
)
@GetMapping(path = "index")
public String index() {
return "index.html";
}
複制
2. WebMvcConfigurer 添加資源映射
除了上述的配置指定之外,還有一種常見的使用姿勢就是利用配置類
WebMvcConfigurer
來手動添加資源映射關系,為了簡單起見,我們直接讓啟動類實作
WebMvcConfigure
接口
@SpringBootApplication
public class Application implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 請注意下面這個映射,将資源路徑 /ts 下的資源,映射到根目錄為 /ts的通路路徑下
// 如 ts下的ts.html, 對應的通路路徑 /ts/ts
registry.addResourceHandler("/ts/**").addResourceLocations("classpath:/ts/");
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
複制
根據上面的配置表示将/ts目錄下的資源ts.html,映射到/ts/ts,而直接通路/ts會報404(這個邏輯可能有點繞,需要仔細想一想)
@GetMapping(path = "ts")
public String ts() {
return "ts.html";
}
@GetMapping(path = "ts/ts")
public String ts2() {
return "ts.html";
}
複制
III. Jar包資源通路
前面描述的靜态資源通路主要都是目前包内的資源通路,如果我們的靜态資源是由第三方的jar包提供(比如大名鼎鼎的Swagger UI),這種時候使用姿勢是否有不一樣的呢?
1. classpath 與 classpath*
在之前使用
SpringMVC3+/4
的時候,
classpath:/META-INF/resources/
表示隻掃描目前包内的
/META-INF/resources/
路徑,而
classpath*:/META-INF/resources/
則會掃描目前+第三方jar包中的
/META-INF/resources/
路徑
那麼在
SpringBoot2.2.1-RELEASE
版本中是否也需要這樣做呢?(答案是不需要,且看後面的執行個體)
2. 執行個體
建立一個工程,隻提供基本的html靜态資源,項目基本結構如下(具體的html内容就不粘貼了,牆裂建議有興趣的小夥伴直接看源碼,閱讀效果更優雅)
接着在我們上面常見的工程中,添加依賴
<dependency>
<groupId>com.git.hui.boot</groupId>
<artifactId>204-web-static-resources-ui</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
複制
添加對應資源的通路端點
@GetMapping(path = "ui")
public String ui() {
return "ui.html";
}
@GetMapping(path = "out")
public String out() {
return "out.html";
}
// 第三方jar包的 META-INF/resources 優先級也高于目前包的 /static
@GetMapping(path = "s2")
public String s2() {
return "s2.html";
}
複制
請注意,這個時候我們是沒有修改前面的
spring.resources.static-locations
配置的
上面的通路結果,除了說明通路第三方jar包中的靜态資源與目前包的靜态資源配置沒有什麼差別之外,還可以得出一點
- 相同資源路徑下,目前包的資源優先級高于jar包中的靜态資源
- 預設配置下,第三方jar包中
下的靜态資源,優先級高于目前包的META-INF/resources
,/resources
,/static
/public
IV. 其他
0. 項目
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源碼:https://github.com/liuyueyi/spring-boot-demo/spring-boot/204-web-static-resources
- https://github.com/liuyueyi/spring-boot-demo/spring-boot/204-web-static-resources-ui
1. 一灰灰Blog
盡信書則不如,以上内容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛
- 一灰灰Blog個人部落格 https://blog.hhui.top
- 一灰灰Blog-Spring專題部落格 http://spring.hhui.top