Spring MVC 核心配置文件详解:springmvc.xml 每一行配置的意义
前言
Spring MVC 项目里,springmvc.xml 是整个请求处理链路的"总装配图"。组件扫描、视图解析、注解驱动、静态资源放行,每一块配置都对应请求从进入到响应出去的某个环节。缺了哪块,对应功能就会失效。
下面逐段拆解一份典型的 springmvc.xml,说明每一项配置的作用、为什么这样配,以及不配会怎样。
一、命名空间与 schemaLocation
xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
这一段是 XML 的语法声明,告诉 Spring 解析器这个文件里会用哪些命名空间、每个命名空间对应的 XSD 在哪里。
xmlns:context:启用<context:...>标签,比如组件扫描。xmlns:mvc:启用<mvc:...>标签,比如注解驱动、静态资源、视图控制器。xsi:schemaLocation:把命名空间 URI 和具体的 XSD 文件地址对应起来,解析器靠它校验标签是否合法。
少了某个命名空间声明,对应标签会报"标签未定义"。schemaLocation 里缺了某个 XSD,解析器找不到标签定义,同样会报错。
注意:mvc 和 context 用的是 https,beans 用的是 http。建议统一成 http,Spring 的 XSD 在 http 下更稳定,https 在某些网络环境或旧解析器下可能拉不到。
二、组件扫描
xml
<context:component-scan base-package="com.xie.springmvc.controller,com.xie.springmvc.dao"/>
作用是让 Spring 扫描指定包及其子包下带有 @Component、@Controller、@Service、@Repository 等注解的类,注册为 Bean。
这里只扫描 controller 和 dao 两个包,没有直接写 com.xie.springmvc。原因是父包下可能还有 entity、dto 等类,这些不需要注册为 Bean,扫描它们只是浪费启动时间。
UserController 在 controller 包下,UserDao 在 dao 包下,两个都会被扫描到。@Controller 和 @Repository 生效后,@Autowired 才能把 UserDao 注入到 UserController 中。
如果扫描范围写错,比如只写了 controller,UserDao 不会被注册,UserController 注入时会报 NoSuchBeanDefinitionException。
三、视图解析器
xml
<bean id="thymeleafViewResolver"
class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8"/>
<property name="order" value="1"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring6.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML"/>
<property name="characterEncoding" value="UTF-8"/>
</bean>
</property>
</bean>
</property>
</bean>
这是一组三层嵌套的 Bean,各负责一件事。
1. ThymeleafViewResolver
把 Controller 返回的逻辑视图名解析成具体的 View 对象。
Controller 返回 "user_index" 时,DispatcherServlet 遍历所有 ViewResolver,ThymeleafViewResolver 拿到视图名,交给 TemplateEngine 渲染,最终生成 HTML 写入响应。
characterEncoding="UTF-8" 控制输出响应的编码,不配中文可能乱码。
order="1" 用于多个视图解析器共存时决定优先级,数值越小越先执行。当前只有一个解析器,配 order 是为以后扩展留余地。
2. SpringTemplateEngine
Thymeleaf 的模板引擎,负责把模板和模型数据合并,生成最终 HTML。它需要知道去哪里找模板、用什么模式解析,这些信息由 templateResolver 提供。
3. SpringResourceTemplateResolver
告诉模板引擎"模板文件在哪里、叫什么后缀、用什么模式解析"。
prefix 和 suffix 决定了模板路径的拼接规则:
prefix + viewName + suffix
= /WEB-INF/templates/ + user_index + .html
= /WEB-INF/templates/user_index.html
所以模板文件必须放在:
src/main/webapp/WEB-INF/templates/user_index.html
前缀、后缀、视图名三者必须和文件实际位置完全对应,否则会报 FileNotFoundException。
templateMode="HTML" 表示按 HTML 模式解析。Thymeleaf 还支持 XML、TEXT、JAVASCRIPT、CSS 等模式。
模板放在 /WEB-INF/ 下,是因为 WEB-INF 目录浏览器无法直接访问,模板只能由服务端渲染,避免用户直接请求 .html 看到未渲染的原始模板。
四、根路径视图控制器
xml
<mvc:view-controller path="/" view-name="user_index"/>
把一个 URL 直接映射到视图名,不需要写 Controller 方法。
访问 / 时,Spring MVC 直接返回视图名 user_index,由 Thymeleaf 解析成 /WEB-INF/templates/user_index.html 并渲染。
如果一个路径只需要返回静态页面,不需要业务逻辑,写一个空 Controller 方法很啰嗦:
java
@GetMapping("/")
public String index() {
return "user_index";
}
<mvc:view-controller> 就是为这种场景准备的,一行配置代替一个方法。
五、注解驱动
xml
<mvc:annotation-driven/>
开启 Spring MVC 的注解驱动,注册一组核心组件:
RequestMappingHandlerMapping和RequestMappingHandlerAdapter,让@RequestMapping、@GetMapping、@PostMapping等注解生效。ExceptionHandlerExceptionResolver,让@ExceptionHandler生效。- 数据绑定、类型转换、格式化相关组件。
- classpath 中有 Jackson 时,自动注册 JSON 消息转换器。
- classpath 中有 JSR-303 校验实现时,自动注册校验相关组件。
没有这行配置,@GetMapping 可能不会被处理,@ResponseBody 的 JSON 序列化也可能不生效。它相当于注解式 Spring MVC 的总开关。
六、静态资源处理
xml
<mvc:resources mapping="/static/**" location="/static/"/>
把 URL 路径 /static/** 映射到 Web 应用下的 /static/ 目录,由 Spring MVC 直接返回静态文件,不经过 Controller。
DispatcherServlet 的 url-pattern 是 /,会拦截所有请求,包括 CSS、JS、图片。没有静态资源处理时,请求 /static/user.css 找不到 Handler,直接 404。
<mvc:resources> 会注册一个 ResourceHttpRequestHandler,专门处理 /static/** 的请求,从 location 指定的目录读取文件并写入响应。
路径对应关系:
mapping="/static/**" → URL 以 /static/ 开头
location="/static/" → 文件在 webapp/static/ 下
所以:
/static/user.css → src/main/webapp/static/user.css
location 是相对于 Web 应用根目录的路径。如果文件放在 WEB-INF/static/ 下,location 要写成 /WEB-INF/static/。
七、默认 Servlet 处理(注释掉的部分)
xml
<!--<mvc:default-servlet-handler/>-->
把所有未匹配到 Controller 的请求,转发给 Web 容器的默认 Servlet 处理。
Tomcat 的默认 Servlet 负责处理静态资源,比如 webapp 根目录下的 HTML、CSS、JS、图片。配置它之后,即使不写 <mvc:resources>,静态资源也能访问。
它和 <mvc:resources> 解决的是同一类问题,只是粒度不同:
<mvc:resources>:精确指定哪些路径由 Spring MVC 处理,控制更细。<mvc:default-servlet-handler/>:把所有未匹配的请求交给容器,范围更宽。
两者同时配置时,<mvc:resources> 优先级更高,<mvc:default-servlet-handler/> 作为兜底。一般项目二选一即可。当前用了 <mvc:resources>,所以把默认 Servlet 处理注释掉,避免职责重叠。
如果以后有大量静态文件放在 webapp 根目录下,不想逐个配 mapping,可以打开这一行。
八、配置清单总结
| 配置 | 作用 | 不配会怎样 |
|---|---|---|
| 命名空间声明 | 让解析器认识 context、mvc 标签 |
标签未定义,启动报错 |
<context:component-scan> |
扫描 Controller 和 Dao,注册为 Bean | @Autowired 注入失败,找不到 Bean |
ThymeleafViewResolver |
把视图名解析成 Thymeleaf 视图 | Controller 返回视图名后无法渲染 |
SpringTemplateEngine |
合并模板和数据,生成 HTML | 视图无法渲染 |
SpringResourceTemplateResolver |
定位模板文件,拼接前缀后缀 | 找不到模板,报 FileNotFoundException |
<mvc:view-controller> |
把 / 直接映射到视图 |
访问根路径 404 |
<mvc:annotation-driven/> |
开启注解驱动,注册核心组件 | @GetMapping 等注解可能不生效 |
<mvc:resources> |
放行静态资源 | CSS、JS 请求 404 |
<mvc:default-servlet-handler/> |
兜底交给容器处理静态资源 | 未匹配请求 404(与 resources 二选一) |
整份配置的核心逻辑是:扫描 Bean → 配置视图解析 → 映射根路径 → 开启注解 → 放行静态资源。每一块都对应 Spring MVC 请求处理链路上的一个环节,理解它们各自的职责,排查问题时就能快速定位是哪一环没配好。