靜態資源處理兩大機制
Java Web 專案中靜態資源(JS、CSS、圖片等)可由兩種方式處理:
| 處理者 | 特性 | 優先級 |
| Tomcat DefaultServlet | 容器原生、效能最佳、支援快取/範圍請求 | 高(配置精確匹配時) |
| Spring MVC ResourceHttpRequestHandler | 框架層、整合攔截器、支援資源鏈 | 中(/ ** 通配時) |
方案一:啟用 Tomcat DefaultServlet(推薦生產環境)
web.xml 精確映射配置
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.ico</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
url-pattern 三種匹配規則
| 類型 | 語法 | 範例 | 優先級 |
| 精確匹配 | /path/to/resource | /api/users | 最高 |
| 路徑匹配 | /path/* | /static/* | 中 |
| 副檔名匹配 | *.ext | *.js | 最低 |
方案二:Spring MVC 資源處理(開發便利)
spring-mvc.xml 配置
<!-- 靜態資源映射:位置 /resources/ 對應 URL /resources/** -->
<mvc:resources location="/resources/" mapping="/resources/**"/>
<!-- 預設 Servlet 處理器:將未匹配請求轉給容器 DefaultServlet -->
<mvc:default-servlet-handler/>
資源鏈進階配置(Spring 4.1+)
<mvc:resources mapping="/assets/**" location="/public/">
<mvc:resource-chain resource-cache="true" auto-registration="true">
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy/>
</mvc:version-resolver>
<mvc:path-extension-resolver/>
</mvc:resolvers>
<mvc:transformers>
<mvc:cache-control-transformer cache-period="31536000"/>
<mvc:gzip-transformer/>
</mvc:transformers>
</mvc:resource-chain>
</mvc:resources>
HandlerMapping 執行順序與優先級
| HandlerMapping | Order 值 | 說明 |
| DefaultAnnotationHandlerMapping | 0 | 註解式 Controller 映射 |
| SimpleUrlHandlerMapping (mvc:resources) | 2147483646 | 靜態資源映射 |
| SimpleUrlHandlerMapping (default-servlet-handler) | 2147483647 | 容器 DefaultServlet 代理 |
原則:Order 數值越小優先執行。Controller 映射 > 靜態資源 > DefaultServlet 代理。
最佳實踐策略
生產環境:容器原生 + Spring 後備
<!-- 1. 精確副檔名交給 Tomcat DefaultServlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
...
<!-- 2. 目錄級交給 DefaultServlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<!-- 3. Spring MVC 兜底:處理資源版本、壓縮等進階功能 -->
<mvc:resources mapping="/resources/**" location="/resources/"/>
<mvc:default-servlet-handler/>
開發環境:Spring MVC 統一處理
<mvc:resources mapping="/**" location="/static/"/>
<mvc:default-servlet-handler/>
常見問題排查
| 現象 | 原因 | 解決 |
| 靜態資源 404 | 映射路徑不匹配 | 檢查 location 實際路徑與 mapping URL 對應 |
| Controller 方法被攔截 | /** 映射優先級過高 | 調整 Order 或改用精確映射 |
| 快取不生效 | 缺少 Cache-Control 標頭 | 配置 resource-chain cache-control-transformer |
| 版本號未生效 | Resolver 順序錯誤 | version-resolver 應在 path-extension-resolver 前 |
Spring Boot 自動配置對應
# application.yml
spring:
mvc:
static-path-pattern: /static/**
resources:
static-locations: classpath:/static/,classpath:/public/
chain:
enabled: true
compressed: true
cache: true
strategy:
content:
enabled: true