Spring MVC 專案啟動後,瀏覽器 Console 顯示 404 無法載入 .js、.css、.png 等靜態資源。這通常是 <mvc:resources> 映射路徑與實際存放位置、或 URL 請求路徑不匹配造成。以下從原理到配置逐步排查。
請求 URL: https://localhost:8080/app/resources/js/main.js
↓ 匹配 mapping="/resources/**"
映射規則:
↓ 解析到 location 指定的物理路徑
物理路徑: src/main/webapp/resources/js/main.js
| 錯誤寫法 | 問題 | 修正 |
|---|---|---|
location="/resources/" 但檔案放在 src/main/resources/static/ | 物理路徑不匹配 | 改為 location="classpath:/static/" 或移動檔案 |
mapping="/static/**" 但前端引用 /resources/xxx.js | 請求路徑與 mapping 不一致 | 統一 mapping 與前端引用路徑前綴 |
缺少 <mvc:default-servlet-handler/> | 預設 Servlet 未處理靜態資源 | 添加或確保 DispatcherServlet mapping 為 / |
| Spring Security 攔截了靜態資源請求 | 安全規則阻擋 | 在 WebSecurityConfigurerAdapter 中 .antMatchers("/resources/**").permitAll() |
src/main/webapp/
├── resources/
│ ├── css/
│ ├── js/
│ └── images/
└── WEB-INF/
└── views/
@Configuration
@EnableWebMvc
@ComponentScan("com.example")
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 瀏覽器請求 /resources/** → 映射到 /resources/ 物理目錄
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/")
.setCachePeriod(3600) // 生產環境建議啟用快取
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); // 關鍵:讓容器預設 Servlet 處理未匹配的靜態資源
}
}
<!-- JSP 使用 JSTL c:url 自動加上 contextPath -->
<%@ taglib prefix="c" uri="https://java.sun.com/jsp/jstl/core" %>
<script src="<c:url value='/resources/js/main.js' />"></script>
<link href="<c:url value='/resources/css/style.css' />" rel="stylesheet" />
<!-- Thymeleaf -->
<script th:src="@{/resources/js/main.js}"></script>
setCachePeriod(0) 開發不快取,生產設長快取。VersionResourceResolver 自動在檔名加入內容雜湊(如 main.a1b2c3.js),解決瀏覽器快取失效問題。.addResourceLocations("https://cdn.example.com/assets/") 多 location 依序查找。https://localhost:8080/你的contextPath/resources/js/main.js,若 404 則映射錯誤;若 200 則前端引用路徑錯誤。target/war-exploded 或 out/artifacts)中是否真有 resources/js/main.js。只要確保 mapping 前綴、location 物理路徑、前端引用路徑、default-servlet-handler 四者一致,靜態資源即可正常載入。
