@EnableWebMvc注解和WebMvcConfigurer接口
- 1,@EnableWebMvc注解
-
- [1.1,@EnableWebMvc 的核心作用](#1.1,@EnableWebMvc 的核心作用)
- [1.2,@EnableWebMvc 的工作原理](#1.2,@EnableWebMvc 的工作原理)
- 1.3,在SpringBoot框架中的应用与注意事项
- 1.4,需用@EnableWebMvc的场景总结
- 2,WebMvcConfigurer接口
- [3,总结:在Spring Boot中自定义 MVC 配置](#3,总结:在Spring Boot中自定义 MVC 配置)
1,@EnableWebMvc注解
@EnableWebMvc是 Spring Framework 中的一个注解,用于在基于 Java 配置的 Spring Web MVC 应用中启用 Spring MVC 的支持 。简单来说,它的作用相当于在传统的 XML 配置文件中使用<mvc:annotation-driven />标签。
1.1,@EnableWebMvc 的核心作用
当在一个带有 @Configuration 注解的配置类上添加 @EnableWebMvc 时,Spring 会自动配置好运行一个 Spring MVC 应用所需的基础组件。
具体来说,它会:
-
启用注解驱动的 MVC(即激活对 @Controller、@RequestMapping、@ResponseBody 等注解的支持),使得 HTTP 请求可以被映射到相应的控制器方法上;
-
提供默认配置:为 Spring MVC 提供一套完整的默认配置,让你能够快速启动和运行一个 Web 应用。
-
同时会自动注册一系列关键的 Bean,例如:
| 方法 | 用途 |
|---|---|
| RequestMappingHandlerMapping | 用于将请求 URL 映射到处理方法 |
| RequestMappingHandlerAdapter | 用于调用处理请求的方法 |
| HandlerExceptionResolver | 用于处理控制器中抛出的异常 |
| MessageConverter | 用于转换 HTTP 请求和响应体(如,将 JSON 字符串转换为 Java 对象) |
1.2,@EnableWebMvc 的工作原理
从该注解的源码层面来看,@EnableWebMvc 的实现非常简洁,其核心是通过 @Import 注解导入了 DelegatingWebMvcConfiguration 类。@EnableWebMvc 源码如下:
java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
DelegatingWebMvcConfiguration继承自WebMvcConfigurationSupport,而后者是 Spring MVC 配置的核心支持类,负责创建和配置上述提到的所有核心组件;- 同时,
DelegatingWebMvcConfiguration还会收集所有实现了WebMvcConfigurer 接口的 Bean,并将它们的配置应用到 Spring MVC 的总配置中,这使得开发者可以方便地覆盖或扩展默认配置。
1.3,在SpringBoot框架中的应用与注意事项
在传统的 Spring MVC 项目(非 Spring Boot项目)中,@EnableWebMvc 是标准配置,用于开启 MVC 功能。
而在 Spring Boot 项目中,情况则完全不同:
Spring Boot 的 spring-boot-starter-web 依赖会通过 WebMvcAutoConfiguration 类自动配置 Spring MVC。这个自动配置会根据你的依赖和配置文件(如 application.properties)来智能地创建 Bean,并提供了很多便利的默认行为,例如:
- 自动配置静态资源路径(如 /static, /public, /resources, /META-INF/resources);
- 自动配置视图解析器;
- 允许通过 application.properties 中的 spring.mvc.* 前缀来配置 MVC;
- ...
但在 Spring Boot 项目中,99% 的场景都不需要 @EnableWebMvc。 因为如果在 Spring Boot 项目中添加 @EnableWebMvc 注解,实际上是完全接管了 Spring MVC 的配置。因为 @EnableWebMvc 会导入 WebMvcConfigurationSupport,而 Spring Boot 的自动配置类 WebMvcAutoConfiguration 上有一个条件注解 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)。这意味着,一旦容器中存在 WebMvcConfigurationSupport 的实例(由 @EnableWebMvc 导入),Spring Boot 的一些自动配置就会失效。

此时 SpringBoot 项目使用 @EnableWebMvc 带来的后果:
- 静态资源访问失效。 无法再通过默认的路径(如 http://localhost:8080/logo.png)访问 static 目录下的静态文件。你需要手动配置资源映射;
- 配置文件属性失效。在 application.properties 或 application.yml 中配置的 spring.mvc 相关属性(如视图前缀/后缀)将不再生效;
- 完全手动配置。此时需要我们自己负责所有 MVC 组件的配置,包括视图解析器、消息转换器、拦截器等。
1.4,需用@EnableWebMvc的场景总结
也就是说使用了 @EnableWebMvc 注解后,必须自己重新实现所有 Spring Boot 原本帮你做好的事情,这样极易出错且增加维护成本。
因此在 Spring Boot 项目中,大多数情况下不需要使用 @EnableWebMvc。需要使用@EnableWebMvc的场景如下:
- 完全不需要 Spring Boot 的 Web 自动配置时;
- 希望从零开始完全控制 Spring MVC 的每一个细节时;
- 在开发一个非 Spring Boot 项目(纯 Spring MVC)时。
2,WebMvcConfigurer接口
WebMvcConfigurer接口是 Spring Framework( Spring Web MVC 模块)中一个非常重要的接口,用于自定义 Spring MVC 的配置,而无需提供完整的@EnableWebMvc配置类。它在 Spring Boot 应用中尤其常见。
2.1,WebMvcConfigurer接口提供的方法
WebMvcConfigurer 提供了一系列默认方法,允许开发者选择性地重写需要定制的行为,部分常用方法如下:
| 方法 | 用途 |
|---|---|
addInterceptors(InterceptorRegistry) |
注册拦截器 |
addCorsMappings(C CorsRegistry) |
配置跨域请求 |
addViewControllers(ViewControllerRegistry) |
配置无逻辑的页面跳转(如 /about → forward:/about.html) |
configurePathMatch(PathMatchConfigurer) |
配置 URL 路径匹配规则(如是否启用后缀模式匹配) |
extendMessageConverters(List<HttpMessageConverter<?>>) |
扩展或替换默认的消息转换器(如 JSON、XML) |
addFormatters(FormatterRegistry) |
添加自定义的类型转换器或格式化器 |
addResourceHandlers(ResourceHandlerRegistry) |
配置静态资源(如 CSS、JS、图片)的访问路径 |
2.2,WebMvcConfigurer接口的使用方式
通常通过实现WebMvcConfigurer接口并用 @Configuration 注解标注的类来使用,eg:
java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
/**
* Spring MVC 的自定义配置类
* 通过实现 WebMvcConfigurer 接口,可以对 Spring Boot 默认的 Web MVC 行为进行扩展或定制,
* 而不会覆盖 Spring Boot 的自动配置(前提是不要添加 @EnableWebMvc 注解)。
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
/**
* 添加自定义拦截器(Interceptor)
* 拦截器可用于在请求处理前后执行通用逻辑,如权限校验、日志记录、性能监控等。
*
* @param registry 拦截器注册器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册一个自定义的拦截器 MyInterceptor,并指定它只拦截 /api/** 路径下的请求
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/api/**"); // 只对以 /api/ 开头的请求生效
// 注意:如果需要排除某些路径,可使用 .excludePathPatterns("/api/public/**")
}
/**
* 配置跨域资源共享(CORS)
* 用于解决浏览器因同源策略而阻止前端(如 Vue、React 应用)调用不同域名的后端接口的问题。
*
* @param registry CORS 映射注册器
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
// 为 /api/** 路径下的所有接口启用 CORS
registry.addMapping("/api/**")
.allowedOrigins("https://example.com") // 允许来自该域名的跨域请求
.allowedMethods("GET", "POST") // 允许的 HTTP 方法
.allowCredentials(true) // 是否允许携带 Cookie(若设为 true,allowedOrigins 不能为 "*")
.maxAge(3600); // 预检请求(preflight)缓存时间(单位:秒)
}
/**
* 配置静态资源处理器
* 默认情况下,Spring Boot 会自动处理 classpath:/static/、/public/ 等目录下的静态资源。
* 此方法可用于自定义静态资源的访问路径或添加额外的资源位置(如外部文件系统路径)。
*
* @param registry 静态资源处理器注册器
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 将 URL 路径 /static/** 映射到类路径下的 /static/ 目录
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600); // 可选:设置浏览器缓存时间(单位:秒)
// 若需映射本地文件系统路径,可使用:file:/opt/uploads/
}
}
注意不要同时使用 @EnableWebMvc 和 WebMvcConfigurer ,除非明确要完全接管 Spring MVC 的自动配置(在 Spring Boot 中会禁用默认的自动配置)。在 Spring Boot 中,推荐仅实现 WebMvcConfigurer 接口而不加 @EnableWebMvc,这样可以保留 Spring Boot 的自动配置(如默认的静态资源处理、欢迎页、错误页等),同时又能灵活扩展。
3,总结:在Spring Boot中自定义 MVC 配置
在绝大多数情况下,如果我们只是想对 Spring Boot 的 MVC 配置进行一些微调(例如添加拦截器、配置消息转换器、增加视图控制器等),就不应该使用 @EnableWebMvc。正确的做法是:创建一个配置类,实现 WebMvcConfigurer 接口。通过实现 WebMvcConfigurer 接口,可以只重写我们关心的配置方法,而不会影响 Spring Boot 的自动配置。这样既能实现自定义,又能保留 Spring Boot 带来的便利。
| 特性 | @EnableWebMvc | 实现 WebMvcConfigurer (Spring Boot 推荐) |
|---|---|---|
| 作用 | 完全启用并接管 Spring MVC 配置 | 对 Spring Boot 的自动 MVC 配置进行扩展或微调 |
| 使用场景 | 1. 传统的、非 Spring Boot 的 Spring MVC 项目。 2. 在 Spring Boot 中需要完全重写所有 MVC 默认配置的极少数情况。 | 在 Spring Boot 项目中进行部分自定义配置,如添加拦截器、视图控制器等。 |
| 对自动配置的影响 | 禁用 Spring Boot 的 WebMvcAutoConfiguration |
不影响,与自动配置协同工作 |
| 静态资源处理 | 需要手动配置 | 由 Spring Boot 自动配置,可被覆盖 |
| 配置文件属性 | application.properties 中的 spring.mvc 属性失效 |
application.properties 中的 spring.mvc 属性依然有效 |
在 Spring Boot 项目中,除非你有非常特殊的理由需要完全控制 MVC 的每一个细节,否则要避免使用 @EnableWebMvc,而应该通过实现 WebMvcConfigurer 接口来进行自定义配置!!!