SpringWeb項目除了我們常見的返回json串之外,還可以直接返回靜態資源(當然在現如今前后端分離比較普遍的情況下,不太常見了),一些簡單的web項目中,前后端可能就一個人包圓了,前端頁面,js/css文件也都直接放在Spring項目中,那么你知道這些靜態資源文件放哪里么
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