天天看點

spingboot html 圖檔,SpringBoot添加對靜态檔案css/html/jpg等的直接通路的支援

請直接看四、解決對策,希望本文解決你的問題

------正文------

一、背景

現在網上大多讨論的是對SpringBoot使用由freemarker等模闆引擎渲染出的html網頁的靜态通路的支援。但是對于一個前後端分離的項目,比如前端使用vue、React等寫,後端使用Spring家族技術等,往往開發者選擇将前端開發的網頁通過webpack等直接打包成含組成網頁的靜态檔案的檔案夾然後交到後端同學手中。比如在/dist下:

spingboot html 圖檔,SpringBoot添加對靜态檔案css/html/jpg等的直接通路的支援

圖1       前端打包的靜态檔案

二、問題産生

一般而言SpringBoot中預設開啟支援浏覽器直接通路這些靜态檔案的,隻要你放在諸如src/main/resources/下的static等就可以使用浏覽器通路。但是有可能像我一樣無法通路,出現類似404的問題(There was an unexpected error (type=Not Found, status=404).):

spingboot html 圖檔,SpringBoot添加對靜态檔案css/html/jpg等的直接通路的支援

圖2      浏覽器無法直接通路靜态資源

三、問題原因猜想

【這裡分析有誤的,請指出,謝謝】浏覽器輸入http://localhost:8080/1.png  (1.png在/src/main/resources/static/1.png),無法通路,檢視Idea的控制台輸出:

spingboot html 圖檔,SpringBoot添加對靜态檔案css/html/jpg等的直接通路的支援

圖3     Idea控制台輸出

意思是找不到處理我的靜态檔案[1.png]的dispatcherServlet,進一步搜尋,大概意思是靜态資源無法映射,這讓我很好奇:靜态資源不是預設有映射的嗎,為什麼需要交給servlet來處理?難道需要把"1.png"和各個RestController中的接口方法的@RequestMapping的值比對嗎?後來在Stack Overflow上發現是預設的映射出了問題。

前面提到過,SpringBoot預設會幫你配置對靜态檔案通路的映射,但是如果你通過某種直接或者其它間接的方式使用了@EnableWebMvc,意思是你想完全地進行web配置,那麼Spring就會忽略預設的配置資訊,去尋找相應的你的設定檔案。如果你沒有設定,就會出現上面這個問題了。

雖然我不知道我哪裡使用了@EnableWebMvc,但是順着這個思路,發現能夠解決這個問題。這個通過結果猜想過程的方法不嚴謹,是以如果有了解錯誤,請大家指出,一是矯正我的錯誤,二是不想讓看我文章的讀者被我誤導,謝謝。

四、解決對策

解決方法是配置WebMvcXXX(多說一句WebMvcConfigurerAdapter在Spring新版本已經過時,是以再看相應的解決方案請慎重)比如建立一個檔案WebConfiguration.java,然後碼上如下代碼:

1 importorg.springframework.context.annotation.Configuration;2 importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;3 importorg.springframework.web.servlet.config.annotation.ViewControllerRegistry;4 importorg.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;5

6 @Configuration7 public class WebConfiguration extendsWebMvcConfigurationSupport {8

9 @Override10 public voidaddResourceHandlers(ResourceHandlerRegistry registry){11 registry.addResourceHandler("/**")12 .addResourceLocations("classpath:/static/");13 }14

15 @Override16 public voidaddViewControllers(ViewControllerRegistry registry) {17 registry.addViewController("/").setViewName("forward:/index.html");18 }19 }

注意:15-18是将"/"映射到"/index.html"去,如果沒有這個需求可以去掉。

如果沒有解決你的問題,請不要放棄,繼續在網際網路上探索了。

五、引用及緻謝

我隻是知識的搬運工,這篇文章離不開他們:

以及其它參考過的網頁