Spring MVC 專案中,靜態資源 (JS、CSS、圖片、字體) 的高效訪問是基礎設施建設的核心環節。本文系統梳理三種主流方案:**Tomcat DefaultServlet 原生映射**、**Spring MVC <mvc:resources>**、**<mvc:default-servlet-handler/>**,並從原理、配置、優先級、最佳實踐四個維度深度對比。
<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>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<!-- 更多副檔名... -->
優點: 繞過 Spring DispatcherServlet、攔截器、過濾器鏈,**性能最高**,由容器原生高效處理靜態文件 IO。
缺點: 配置繁瑣 (需列舉所有副檔名)、耦合容器 (遷移 Jetty/Undertow 需改配置)、無法利用 Spring 資源抽象 (如 classpath:/、主題解析)。
url-pattern 三種寫法補充| 類型 | 語法 | 示例 | 匹配規則 |
|---|---|---|---|
| 精確匹配 | 以 / 開頭 | /api/user | 完全匹配路徑 |
| 路徑匹配 | /xxx/* | /resources/* | 前綴匹配目錄樹 |
| 副檔名匹配 | *.xxx | *.js | 匹配所有以 .js 結尾的請求 |
<mvc:resources> (功能最豐富)<mvc:resources mapping="/resources/**" location="/resources/" /> <!-- 多目錄映射 --> <mvc:resources mapping="/static/**" location="/static/, classpath:/META-INF/web-static/" />
mapping:請求路徑前綴 (如 /resources/**)。location:資源物理位置,**支援多路徑**、**支援 classpath:** 訪問 Jar 包內資源 (WebJars 核心機制)。<mvc:resources mapping="/assets/**" location="/assets/">
<!-- 緩存控制:一年過期 + 公共緩存 -->
<mvc:cache-control max-age="31536000" cache-public="true"/>
<!-- 鏈式解析器:版本號、GZIP、PathVariable -->
<mvc:resource-chain resource-cache="true" auto-registration="true">
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>
核心優勢: 緩存控制、版本管理 (MD5 內容哈希)、GZIP 預壓縮、WebJars 整合、主題切換 — **企業級靜態資源管理首選**。
<mvc:default-servlet-handler/> (折中方案)<mvc:default-servlet-handler/>
DefaultServletHttpRequestHandler 到 SimpleUrlHandlerMapping,映射路徑 /**。Spring 根據 Ordered 接口的 order 值決定 HandlerMapping 執行順序,**值越小優先級越高**:
| HandlerMapping 類型 | order 值 | 優先級 | 說明 |
|---|---|---|---|
RequestMappingHandlerMapping (註解式 Controller) | 0 | 最高 | 優先匹配 @RequestMapping |
<mvc:resources> 註冊的 SimpleUrlHandlerMapping | 2147483646 | 中 | 靜態資源映射 |
<mvc:default-servlet-handler/> 註冊的 SimpleUrlHandlerMapping | 2147483647 (Integer.MAX_VALUE - 1) | 最低 | 兜底轉發 DefaultServlet |
實戰含義:
/api/users)。<mvc:resources> 映射 (/resources/app.js)。<mvc:default-servlet-handler/> 兜底 (/favicon.ico、未知靜態文件)。<mvc:resources> + Resource Chain**,享受緩存、版本、WebJars 完整特性;配置 <mvc:default-servlet-handler/> 作為終極兜底。<mvc:resources mapping="/**" ...> **切勿映射根路徑**,會攔截所有請求導致 Controller 失效;請用具體前綴如 /static/**、/assets/**。DefaultServlet 映射:性能王者,配置繁瑣,適合極致性能場景。
<mvc:resources>:功能王者,企業級特性全備,現代 Spring MVC **標準配置**。
<mvc:default-servlet-handler/>:配置極簡,兜底利器,但走 Spring 鏈有微小開銷。
**推薦組合:** <mvc:resources mapping="/static/**" location="/static/"/> + <mvc:default-servlet-handler/> + **生產環境上 CDN**。這樣既享受開發期便利,又保證生產環境極致性能與架構彈性。