【SpringBoot WEB系列】靜態資源配置與讀取


【WEB系列】靜態資源配置與讀取

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. 項目

1. 一灰灰Blog

盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

下面一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛

一灰灰blog


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM