1. 程式人生 > >Spring Boot2 系列教程(十一)Spring Boot 中的靜態資源配置

Spring Boot2 系列教程(十一)Spring Boot 中的靜態資源配置

當我們使用 SpringMVC 框架時,靜態資源會被攔截,需要新增額外配置,之前老有小夥伴在微信上問鬆哥 Spring Boot 中的靜態資源載入問題:“鬆哥,我的 HTML 頁面好像沒有樣式?”,今天我就通過一篇文章,來和大夥仔細聊一聊這個問題。

1. SSM 中的配置

要講 Spring Boot 中的問題,我們得先回到 SSM 環境搭建中,一般來說,我們可以通過 <mvc:resources /> 節點來配置不攔截靜態資源,如下:

<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/html/**" location="/html/"/>

由於這是一種Ant風格的路徑匹配符,/** 表示可以匹配任意層級的路徑,因此上面的程式碼也可以像下面這樣簡寫:

<mvc:resources mapping="/**" location="/"/>

這種配置是在 XML 中的配置,大家知道,SpringMVC 的配置除了在XML中配置,也可以在 Java 程式碼中配置,如果在 Java 程式碼中配置的話,我們只需要自定義一個類,繼承自 WebMvcConfigurationSupport 即可:

@Configuration
@ComponentScan(basePackages = "org.javaboy.javassm")
public class SpringMVCConfig extends WebMvcConfigurationSupport {
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("/");
    }
}

重寫 WebMvcConfigurationSupport 類中的 addResourceHandlers 方法,在該方法中配置靜態資源位置即可,這裡的含義和上面 xml 配置的含義一致,因此無需多說。

這是我們傳統的解決方案,在 Spring Boot 中,其實配置方式和這個一脈相承,只是有一些自動化的配置了。

2. Spring Boot 中的配置

在 Spring Boot 中,如果我們是從 https://start.spring.io 這個網站上建立的專案,或者使用 IntelliJ IDEA 中的 Spring Boot 初始化工具建立的專案,預設都會存在 resources/static

目錄,很多小夥伴也知道靜態資源只要放到這個目錄下,就可以直接訪問,除了這裡還有沒有其他可以放靜態資源的位置呢?為什麼放在這裡就能直接訪問了呢?這就是本文要討論的問題了。

2.1 整體規劃

首先,在 Spring Boot 中,預設情況下,一共有 5 個位置可以放靜態資源,五個路徑分別是如下 5 個:

  1. classpath:/META-INF/resources/
  2. classpath:/resources/
  3. classpath:/static/
  4. classpath:/public/
  5. /

前四個目錄好理解,分別對應了 resources 目錄下不同的目錄,第 5 個 / 是啥意思呢?我們知道,在 Spring Boot 專案中,預設是沒有 webapp 這個目錄的,當然我們也可以自己新增(例如在需要使用JSP的時候),這裡第 5 個 / 其實就是表示 webapp 目錄中的靜態資源也不被攔截。如果同一個檔案分別出現在五個目錄下,那麼優先順序也是按照上面列出的順序。

不過,雖然有 5 個儲存目錄,除了第 5 個用的比較少之外,其他四個,系統預設建立了 classpath:/static/ , 正常情況下,我們只需要將我們的靜態資源放到這個目錄下即可,也不需要額外去建立其他靜態資源目錄,例如我在 classpath:/static/ 目錄下放了一張名為 1.png 的圖片,那麼我的訪問路徑是:

http://localhost:8080/1.png

這裡大家注意,請求地址中並不需要 static,如果加上了 static 反而多此一舉會報 404 錯誤。很多人會覺得奇怪,為什麼不需要新增 static 呢?資源明明放在 static 目錄下。其實這個效果很好實現,例如在 SSM 配置中,我們的靜態資源攔截配置如果是下面這樣:

<mvc:resources mapping="/**" location="/static/"/>

如果我們是這樣配置的話,請求地址如果是 http://localhost:8080/1.png 實際上系統會去 /static/1.png 目錄下查詢相關的檔案。

所以我們理所當然的猜測,在 Spring Boot 中可能也是類似的配置。

2.2 原始碼解讀

胡適之先生說:“大膽猜想,小心求證”,我們這裡就通過原始碼解讀來看看 Spring Boot 中的靜態資源到底是怎麼配置的。

首先我們在 WebMvcAutoConfiguration 類中看到了 SpringMVC 自動化配置的相關的內容,找到了靜態資源攔截的配置,如下:

可以看到這裡靜態資源的定義和我們前面提到的 Java 配置 SSM 中的配置非常相似,其中,this.mvcProperties.getStaticPathPattern() 方法對應的值是 /**,this.resourceProperties.getStaticLocations() 方法返回了四個位置,分別是:

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/

然後在 getResourceLocations 方法中,又添加了 / ,因此這裡返回值一共有 5 個。其中, / 表示 webapp 目錄,即 webapp 中的靜態檔案也可以直接訪問。靜態資源的匹配路徑按照定義路徑優先順序依次降低。因此這裡的配置和我們前面提到的如出一轍。這樣大夥就知道了為什麼 Spring Boot 中支援 5 個靜態資源位置,同時也明白了為什麼靜態資源請求路徑中不需要 /static ,因為在路徑對映中已經自動的新增上了 /static 了。

2.3 自定義配置

當然,這個是系統預設配置,如果我們並不想將資源放在系統預設的這五個位置上,也可以自定義靜態資源位置和對映,自定義的方式也有兩種,可以通過 application.properties 來定義,也可以在 Java 程式碼中來定義,下面分別來看。

2.3.1 application.properties

在配置檔案中定義的方式比較簡單,如下:

spring.resources.static-locations=classpath:/
spring.mvc.static-path-pattern=/**

第一行配置表示定義資源位置,第二行配置表示定義請求 URL 規則。以上文的配置為例,如果我們這樣定義了,表示可以將靜態資源放在 resources 目錄下的任意地方,我們訪問的時候當然也需要寫完整的路徑,例如在 resources/static 目錄下有一張名為 1.png 的圖片,那麼訪問路徑就是 http://localhost:8080/static/1.png ,注意此時的 static 不能省略。

2.3.2 Java 程式碼定義

當然,在 Spring Boot 中我們也可以通過 Java 程式碼來自定義,方式和 Java 配置的 SSM 比較類似,如下:

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/aaa/");
    }
}

這裡程式碼基本和前面一致,比較簡單,不再贅述。

3. 總結

這裡需要提醒大家的是,鬆哥見到有很多人用了 Thymeleaf 之後,會將靜態資源也放在 resources/templates 目錄下,注意,templates 目錄並不是靜態資源目錄,它是一個放頁面模板的位置(你看到的 Thymeleaf 模板雖然後綴為 .html,其實並不是靜態資源)。好了,通過上面的講解,相信大家對 Spring Boot 中靜態資源的位置有一個深刻了解了,應該不會再在專案中出錯了吧!

關注公眾號【江南一點雨】,專注於 Spring Boot+微服務以及前後端分離等全棧技術,定期視訊教程分享,關注後回覆 Java ,領取鬆哥為你精心準備的 Java 乾貨!

相關推薦

Spring Boot2 系列教程()Spring Boot 靜態資源配置

當我們使用 SpringMVC 框架時,靜態資源會被攔截,需要新增額外配置,之前老有小夥伴在微信上問鬆哥 Spring Boot 中的靜態資源載入問題:“鬆哥,我的 HTML 頁面好像沒有樣式?”,今天我就通過一篇文章,來和大夥仔細聊一聊這個問題。 1. SSM 中的配置 要講 Spring Boot 中的問

Spring Boot2 系列教程(八)Spring Boot 自定義 SpringMVC 配置

用過 Spring Boot 的小夥伴都知道,我們只需要在專案中引入 spring-boot-starter-web 依賴,SpringMVC 的一整套東西就會自動給我們配置好,但是,真實的專案環境比較複雜,系統自帶的配置不一定滿足我們的需求,往往我們還需要結合實際情況自定義配置。 自定義配置就有講究了,由於

Spring Boot2 系列教程(九)Spring Boot 整合 JdbcTemplate

在 Java 領域,資料持久化有幾個常見的方案,有 Spring 自帶的 JdbcTemplate 、有 MyBatis,還有 JPA,在這些方案中,最簡單的就是 Spring 自帶的 JdbcTemplate 了,這個東西雖然沒有 MyBatis 那麼方便,但是比起最開始的 Jdbc 已經強了很多了,它沒有

Spring Boot2 系列教程()Spring Boot 整合 Freemarker

今天來聊聊 Spring Boot 整合 Freemarker。 Freemarker 簡介 這是一個相當老牌的開源的免費的模版引擎。通過 Freemarker 模版,我們可以將資料渲染成 HTML 網頁、電子郵件、配置檔案以及原始碼等。Freemarker 不是面向終端使用者的,而是一個 Java 類庫,我

Spring Boot2 系列教程(二)建立 Spring Boot 專案的三種方式

我最早是 2016 年底開始寫 Spring Boot 相關的部落格,當時使用的版本還是 1.4.x ,文章發表在 CSDN 上,閱讀量最大的一篇有 43W+,如下圖: 2017 年由於種種原因,就沒有再繼續更新 Spring Boot 相關的部落格了,2018年又去寫書了,也沒更新,現在 Spring

Spring Boot2 系列教程(三)理解 Spring Boot 專案的 parent

前面和大夥聊了 Spring Boot 專案的三種建立方式,這三種建立方式,無論是哪一種,建立成功後,pom.xml 座標檔案中都有如下一段引用: <parent> <groupId>org.springframework.boot</groupId> &l

Spring Boot2 系列教程(四)理解Spring Boot 配置檔案 application.properties

在 Spring Boot 中,配置檔案有兩種不同的格式,一個是 properties ,另一個是 yaml 。 雖然 properties 檔案比較常見,但是相對於 properties 而言,yaml 更加簡潔明瞭,而且使用的場景也更多,很多開源專案都是使用 yaml 進行配置(例如 Hexo)。除了簡潔

Spring Boot2 系列教程(二)@ControllerAdvice 的三種使用場景

嚴格來說,本文並不算是 Spring Boot 中的知識點,但是很多學過 SpringMVC 的小夥伴,對於 @ControllerAdvice 卻並不熟悉,Spring Boot 和 SpringMVC 一脈相承,@ControllerAdvice 在 Spring Boot 中也有廣泛的使用場景,因此本文

Spring Boot2 系列教程(四)CORS 解決跨域問題

今天和小夥伴們來聊一聊通過CORS解決跨域問題。 同源策略 很多人對跨域有一種誤解,以為這是前端的事,和後端沒關係,其實不是這樣的,說到跨域,就不得不說說瀏覽器的同源策略。 同源策略是由 Netscape 提出的一個著名的安全策略,它是瀏覽器最核心也最基本的安全功能,現在所有支援 JavaScript 的瀏覽

Spring Boot2 系列教程(五)定義系統啟動任務的兩種方式

在 Servlet/Jsp 專案中,如果涉及到系統任務,例如在專案啟動階段要做一些資料初始化操作,這些操作有一個共同的特點,只在專案啟動時進行,以後都不再執行,這裡,容易想到web基礎中的三大元件( Servlet、Filter、Listener )之一 Listener ,這種情況下,一般定義一個 Serv

Spring Boot2 系列教程(六)定時任務的兩種實現方式

在 Spring + SpringMVC 環境中,一般來說,要實現定時任務,我們有兩中方案,一種是使用 Spring 自帶的定時任務處理器 @Scheduled 註解,另一種就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具備這兩個 Spring

Spring Boot2 系列教程(七)SpringBoot 整合 Swagger2

前後端分離後,維護介面文件基本上是必不可少的工作。 一個理想的狀態是設計好後,介面文件發給前端和後端,大夥按照既定的規則各自開發,開發好了對接上了就可以上線了。當然這是一種非常理想的狀態,實際開發中卻很少遇到這樣的情況,介面總是在不斷的變化之中,有變化就要去維護,做過的小夥伴都知道這件事有多麼頭大!還好,有一

Spring Boot2 系列教程(三)Spring Boot 構建 RESTful 風格應用

RESTful ,到現在相信已經沒人不知道這個東西了吧!關於 RESTful 的概念,我這裡就不做過多介紹了,傳統的 Struts 對 RESTful 支援不夠友好 ,但是 SpringMVC 對於 RESTful 提供了很好的支援,常見的相關注解有: @RestController @GetMapping

Spring Boot系列教程: Mybatis使用分頁外掛PageHelper

一.前言 上篇部落格中介紹了spring boot整合mybatis的方法,基於上篇文章這裡主要介紹如何使用分頁外掛PageHelper。在MyBatis中提供了攔截器介面,我們可以使用PageHelp最為一個外掛裝入到SqlSessionFactory,實現攔截器功能。

Spring Boot2 系列教程(二)整合 MyBatis

前面兩篇文章和讀者聊了 Spring Boot 中最簡單的資料持久化方案 JdbcTemplate,JdbcTemplate 雖然簡單,但是用的並不多,因為它沒有 MyBatis 方便,在 Spring+SpringMVC 中整合 MyBatis 步驟還是有點複雜的,要配置多個 Bean,Spring Boo

Spring Boot2 系列教程(二四)Spring Boot 整合 Jpa

Spring Boot 中的資料持久化方案前面給大夥介紹了兩種了,一個是 JdbcTemplate,還有一個 MyBatis,JdbcTemplate 配置簡單,使用也簡單,但是功能也非常有限,MyBatis 則比較靈活,功能也很強大,據我所知,公司採用 MyBatis 做資料持久化的相當多,但是 MyBat

Spring Boot2 系列教程(二五)Spring Boot 整合 Jpa 多資料來源

本文是 Spring Boot 整合資料持久化方案的最後一篇,主要和大夥來聊聊 Spring Boot 整合 Jpa 多資料來源問題。在 Spring Boot 整合JbdcTemplate 多資料來源、Spring Boot 整合 MyBatis 多資料來源以及 Spring Boot 整合 Jpa 多資料

Spring Boot2 系列教程(二六)Spring Boot 整合 Redis

在 Redis 出現之前,我們的快取框架各種各樣,有了 Redis ,快取方案基本上都統一了,關於 Redis,鬆哥之前有一個系列教程,尚不瞭解 Redis 的小夥伴可以參考這個教程: Redis 教程合集 使用 Java 操作 Redis 的方案很多,Jedis 是目前較為流行的一種方案,除了 Jedi

Spring Boot2 系列教程(二八)Spring Boot 整合 Session 共享

這篇文章是鬆哥的原創,但是在第一次釋出的時候,忘了標記原創,結果被好多號轉發,導致我後來整理的時候自己沒法標記原創了。寫了幾百篇原創技術乾貨了,有一兩篇忘記標記原創進而造成的一點點小小損失也能接受,不過還是要和小夥伴們說明一下。 在傳統的單服務架構中,一般來說,只有一個伺服器,那麼不存在 Session

Spring Boot2 系列教程(二九)Spring Boot 整合 Redis

經過 Spring Boot 的整合封裝與自動化配置,在 Spring Boot 中整合Redis 已經變得非常容易了,開發者只需要引入 Spring Data Redis 依賴,然後簡單配下 redis 的基本資訊,系統就會提供一個 RedisTemplate 供開發者使用,但是今天鬆哥想和大夥聊的不是這種