在 Spring MVC 專案中,applicationContext.xml(常命名為 root-context.xml)與 spring-servlet.xml(常命名為 servlet-context.xml)是兩個核心配置文件,它們分別對應 Spring 容器的兩個層級:根容器與Servlet 容器。混淆兩者會導致 Bean 重複創建、事務失效、依賴注入失敗等疑難雜癥。本文從文件位置、作用域、web.xml 加載配置三個維度徹底釐清兩者關係。
雖然文件名可自定義,但遵循慣例有利於團隊協作:
WEB-INF/spring/ 或 WEB-INF/ 目錄下,屬於專案級全局配置。WEB-INF/spring/appServlet/ 或 WEB-INF/ 更深層目錄,屬於特定 DispatcherServlet 專用配置。
| 維度 | applicationContext.xml (根容器) | spring-servlet.xml (Servlet 容器) |
|---|---|---|
| 容器層級 | 根應用上下文 | DispatcherServlet 子上下文 |
| 作用範圍 | 全局(Service、DAO、DataSource、TransactionManager 等業務組件) | Web 層(Controller、ViewResolver、HandlerMapping、Interceptor 等) |
| 父子關係 | 父容器 | 子容器(可訪問父容器 Bean,父不可訪問子) |
| 生命週期 | 隨 ServletContext 銷毀 | 隨 DispatcherServlet 銷毀 |
| 典型配置項 | 數據源、事務管理、MyBatis/SQLSessionFactory、Service Bean、AOP 切面 | Controller 掃描、視圖解析器、靜態資源映射、攔截器、MultipartResolver |
關鍵原則:業務邏輯組件(Service、DAO)放入根容器,確保單例、事務生效;Web 控制組件放入 Servlet 容器,避免多 Servlet 共享 Controller 導致狀態混亂。
根容器由 ContextLoaderListener 啟動,Servlet 容器由 DispatcherServlet 初始化時自動加載:
<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee
https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>SpringMVC-Demo</display-name>
<!-- 1. 根容器啟動監聽器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- 2. Spring MVC 前端控制器 -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
spring-servlet.xml 中掃描 @Service、@Repository 導致雙份 Bean,事務註解 @Transactional 失效。
com.xxx.service、com.xxx.dao;Servlet 容器僅掃描 com.xxx.controller。
applicationContext.xml 構建應用骨架(數據訪問、事務、業務邏輯),spring-servlet.xml 構建 Web 表現層(路由、視圖、參數綁定)。父子容器機制實現了「業務邏輯單例全局共享,Web 組件請求級隔離」的架構目標。配置時請嚴格遵循分層原則,避免跨層掃描與重複定義。