Spring Boot 中的靜態資源到底要放在哪裏?

當咱們使用 SpringMVC 框架時,靜態資源會被攔截,須要添加額外配置,以前老有小夥伴在微信上問鬆哥Spring Boot 中的靜態資源加載問題:「鬆哥,個人HTML頁面好像沒有樣式?」,今天我就經過一篇文章,來和大夥仔細聊一聊這個問題。css

SSM 中的配置

要講 Spring Boot 中的問題,咱們得先回到 SSM 環境搭建中,通常來講,咱們能夠經過 <mvc:resources /> 節點來配置不攔截靜態資源,以下:html

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

因爲這是一種Ant風格的路徑匹配符,/** 表示能夠匹配任意層級的路徑,所以上面的代碼也能夠像下面這樣簡寫:java

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

這種配置是在 XML 中的配置,你們知道,SpringMVC 的配置除了在XML中配置,也能夠在 Java 代碼中配置,若是在Java代碼中配置的話,咱們只須要自定義一個類,繼承自WebMvcConfigurationSupport便可:web

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

重寫 WebMvcConfigurationSupport 類中的addResourceHandlers方法,在該方法中配置靜態資源位置便可,這裏的含義和上面 xml 配置的含義一致,所以無需多說。
這是咱們傳統的解決方案,在Spring Boot 中,其實配置方式和這個一脈相承,只是有一些自動化的配置了。spring

Spring Boot 中的配置

在 Spring Boot 中,若是咱們是從 https://start.spring.io 這個網站上建立的項目,或者使用 IntelliJ IDEA 中的 Spring Boot 初始化工具建立的項目,默認都會存在 resources/static 目錄,不少小夥伴也知道靜態資源只要放到這個目錄下,就能夠直接訪問,除了這裏還有沒有其餘能夠放靜態資源的位置呢?爲何放在這裏就能直接訪問了呢?這就是本文要討論的問題了。微信

總體規劃

首先,在 Spring Boot 中,默認狀況下,一共有5個位置能夠放靜態資源,五個路徑分別是以下5個:mvc

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

前四個目錄好理解,分別對應了resources目錄下不一樣的目錄,第5個 / 是啥意思呢?咱們知道,在 Spring Boot 項目中,默認是沒有 webapp 這個目錄的,固然咱們也能夠本身添加(例如在須要使用JSP的時候),這裏第5個 / 其實就是表示 webapp 目錄中的靜態資源也不被攔截。若是同一個文件分別出如今五個目錄下,那麼優先級也是按照上面列出的順序。app

不過,雖然有5個存儲目錄,除了第5個用的比較少以外,其餘四個,系統默認建立了 classpath:/static/ , 正常狀況下,咱們只須要將咱們的靜態資源放到這個目錄下便可,也不須要額外去建立其餘靜態資源目錄,例如我在 classpath:/static/ 目錄下放了一張名爲1.png 的圖片,那麼個人訪問路徑是:框架

http://localhost:8080/1.png

這裏你們注意,請求地址中並不須要 static,若是加上了static反而畫蛇添足會報404錯誤。不少人會以爲奇怪,爲何不須要添加 static呢?資源明明放在 static 目錄下。其實這個效果很好實現,例如在SSM配置中,咱們的靜態資源攔截配置若是是下面這樣:webapp

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

若是咱們是這樣配置的話,請求地址若是是 http://localhost:8080/1.png 實際上系統會去 /static/1.png 目錄下查找相關的文件。

因此咱們理所固然的猜想,在 Spring Boot 中可能也是相似的配置。

源碼解讀

胡適之先生說:「大膽猜測,當心求證」,咱們這裏就經過源碼解讀來看看 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了。

自定義配置

固然,這個是系統默認配置,若是咱們並不想將資源放在系統默認的這五個位置上,也能夠自定義靜態資源位置和映射,自定義的方式也有兩種,能夠經過 application.properties 來定義,也能夠在 Java 代碼中來定義,下面分別來看。

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不能省略。

Java 代碼定義

固然,在Spring Boot中咱們也能夠經過 Java代碼來自定義,方式和 Java 配置的 SSM 比較相似,以下:

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

這裏代碼基本和前面一致,比較簡單,再也不贅述。

總結

這裏須要提醒你們的是,鬆哥見到有不少人用了 Thymeleaf 以後,會將靜態資源也放在 resources/templates 目錄下,注意,templates 目錄並非靜態資源目錄,它是一個放頁面模板的位置(你看到的 Thymeleaf 模板雖而後綴爲 .html,其實並非靜態資源)。好了,經過上面的講解,相信你們對 Spring Boot 中靜態資源的位置有一個深入瞭解了,應該不會再在項目中出錯了吧!

更多資料,請關注公衆號牧碼小子,回覆 Java, 獲取鬆哥爲你精心準備的Java乾貨!

相關文章
相關標籤/搜索