spring 中的 @EnableWebMvc注解和WebMvcConfigurer接口

一句话总结

  • 非 Spring Boot 项目:@EnableWebMvc + WebMvcConfigurer 是标准组合。
  • Spring Boot 项目:‌只实现 WebMvcConfigurer 就够了‌,不要加 @EnableWebMvc,除非你确实想完全接管 MVC 配置。‌‌

@EnableWebMvc注解

@EnableWebMvc 是 Spring Framework 中的一个注解,用于在基于 Java 配置的 Spring Web MVC 应用中启用 Spring MVC 的支持。简单来说,它的作用相当于在传统的 XML 配置文件中使用 <mvc:annotation-driven /> 标签。

@EnableWebMvc 的核心作用

当在一个带有 @Configuration 注解的配置类上添加 @EnableWebMvc 时,Spring 会自动配置好运行一个 Spring MVC 应用所需的基础组件。具体来说,它会:

启用注解驱动的 MVC(即激活对 @Controller、@RequestMapping、@ResponseBody 等注解的支持),使得 HTTP 请求可以被映射到相应的控制器方法上;

提供默认配置:为 Spring MVC 提供一套完整的默认配置,让你能够快速启动和运行一个 Web 应用。

同时会自动注册一系列关键的 Bean,例如:

| 方法 | 用途 |
| RequestMappingHandlerMapping | 用于将请求 URL 映射到处理方法 |
| RequestMappingHandlerAdapter | 用于调用处理请求的方法 |
| HandlerExceptionResolver | 用于处理控制器中抛出的异常 |

MessageConverter 用于转换 HTTP 请求和响应体(如,将 JSON 字符串转换为 Java 对象)

@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 的总配置中,这使得开发者可以方便地覆盖或扩展默认配置。

在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 的配置。因为:

  • Spring Boot 的自动配置类 WebMvcAutoConfiguration 上有个条件注解 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)。这意味着,一旦容器中存在 WebMvcConfigurationSupport 的实例(由 @EnableWebMvc 导入),Spring Boot 的一些自动配置就会失效。只有当 Spring 容器中不存在 WebMvcConfigurationSupport 类型的 Bean 时,WebMvcAutoConfiguration 才会生效。
  • 而@EnableWebMvc 注解通过 @Import 导入 DelegatingWebMvcConfiguration 这个配置类。DelegatingWebMvcConfiguration 继承自 WebMvcConfigurationSupport,因此它本身就是一个 WebMvcConfigurationSupport 类型的Bean。因此,当 DelegatingWebMvcConfiguration 被注册到容器后,WebMvcAutoConfiguration 就会随之失效。

此时 SpringBoot 项目使用 @EnableWebMvc 带来的后果:

  • 静态资源访问失效。 无法再通过默认的路径(如 http://localhost:8080/logo.png)访问 static 目录下的静态文件。你需要手动配置资源映射;
  • 配置文件属性失效。在 application.properties 或 application.yml 中配置的 spring.mvc 相关属性(如视图前缀/后缀)将不再生效;
  • 完全手动配置。此时需要我们自己负责所有 MVC 组件的配置,包括视图解析器、消息转换器、拦截器等。

需用@EnableWebMvc的场景总结

也就是说使用了 @EnableWebMvc 注解后,必须自己重新实现所有 Spring Boot 原本帮你做好的事情,这样极易出错且增加维护成本。因此在 Spring Boot 项目中,大多数情况下不需要使用 @EnableWebMvc。需要使用@EnableWebMvc的场景如下:

  • 完全不需要 Spring Boot 的 Web 自动配置时;
  • 希望从零开始完全控制 Spring MVC 的每一个细节时;
  • 在开发一个非 Spring Boot 项目(纯 Spring MVC)时。

WebMvcConfigurer接口

WebMvcConfigurer接口 是 Spring Framework( Spring Web MVC 模块)中一个非常重要的接口,用于自定义 Spring MVC 的配置,而无需提供完整的 @EnableWebMvc 配置类。它在 Spring Boot 应用中尤其常见。

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、图片)的访问路径

注意不要同时使用 @EnableWebMvc 和 WebMvcConfigurer,除非明确要完全接管 Spring MVC 的自动配置(在 Spring Boot 中会禁用默认的自动配置)。在 Spring Boot 中,推荐仅实现 WebMvcConfigurer 接口而不加 @EnableWebMvc,这样可以保留 Spring Boot 的自动配置(如默认的静态资源处理、欢迎页、错误页等),同时又能灵活扩展。

原理:当我们创建了一个带有 @Configuration 注解的类,并实现了 WebMvcConfigurer 接口。此时:

  • @Configuration 注解告诉 Spring 容器:"这是一个配置类,请把我管理起来。" Spring 启动时进行组件扫描,会把这个类识别出来并注册为一个 Bean;
  • Spring Boot 的 MVC 自动配置核心类 WebMvcAutoConfiguration 内部,有一个名为 EnableWebMvcConfiguration 的类 。这个配置类继承自 DelegatingWebMvcConfiguration。(DelegatingWebMvcConfiguration继承自WebMvcConfigurationSupport);
  • DelegatingWebMvcConfiguration 的关键作用在于,它会利用依赖注入,自动查找 Spring 容器中所有实现了 WebMvcConfigurer 接口的 Bean;
  • DelegatingWebMvcConfiguration 会遍历它收集到的所有 WebMvcConfigurer 实例,并依次调用它们被重写的方法。这意味着,我们添加的自定义配置和 Spring Boot 默认的 MVC 配置会被合并在一起,共同生效;

总结:在Spring Boot中自定义 MVC 配置

在绝大多数情况下,如果我们只是想对 Spring Boot 的 MVC 配置进行一些微调(例如添加拦截器、配置消息转换器、增加视图控制器等),就不应该使用 @EnableWebMvc。正确的做法是:创建一个配置类,实现 WebMvcConfigurer 接口。通过实现 WebMvcConfigurer 接口,可以只重写我们关心的配置方法,而不会影响 Spring Boot 的自动配置。这样既能实现自定义,又能保留 Spring Boot 带来的便利。

在非springboot工程中

@EnableWebMvc 是"开关",WebMvcConfigurer 是"定制接口"‌,两者常搭配使用,但作用完全不同。

  • ‌@EnableWebMvc‌:开启 Spring MVC 的注解驱动配置,相当于 XML 里的 <mvc:annotation-driven />。它通过 @Import(DelegatingWebMvcConfiguration.class) 导入一个 WebMvcConfigurationSupport 的子类,由这个子类去创建 MVC 的核心组件(如 RequestMappingHandlerMapping、消息转换器等)。
  • ‌WebMvcConfigurer‌:一个回调接口,里面全是 default 方法,用来定制 MVC 的配置,比如加拦截器、配跨域、自定义静态资源映射、配置视图解析器等。它本身不"开启"任何功能,只是提供扩展点

在‌非 Spring Boot 的纯 Spring MVC 项目‌里,通常这样用:

java 复制代码
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    //配置jsp页面位置
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp("/WEB-INF/views/",".jsp");
    }

    /**
     * 开启静态资源查找
     * dispatcherServlet  通知  handlerMapping根据静态资源路径找对应的handler  若没找到
     *        如果不开启静态资源查找,请求返回给dispatcherServlet后直接再返回给前端,404异常。
     *        如果开启了静态资源查找,
              就会再调用 defaultServletHandler查找静态资源(拿着静态资源路径做了一次转发。)
     */
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

@EnableWebMvc 导入的 DelegatingWebMvcConfiguration 会‌自动收集容器里所有 WebMvcConfigurer 的 Bean‌,并把它们的配置合并到 MVC 全局配置中。‌‌

在 Spring Boot 里要特别注意

Spring Boot 已经通过 WebMvcAutoConfiguration 自动配置好了 MVC,‌默认情况下不需要加 @EnableWebMvc‌,只需实现 WebMvcConfigurer 做增量定制即可。‌‌

一旦加了 @EnableWebMvc,它会导入 DelegatingWebMvcConfiguration(它是 WebMvcConfigurationSupport 的子类),而 WebMvcAutoConfiguration 上有 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class),条件不满足,‌Spring Boot 的 MVC 自动配置会整个失效‌------静态资源映射、默认消息转换器、spring.mvc 配置项等全部丢失,需要手动补齐。‌‌

相关推荐
卷无止境1 小时前
Skill 的安全边界在哪里:风险来源、验证思路与用户可用的防线
后端·python
香蕉大香蕉(06敬畏市场)2 小时前
高频八股 · JVM(8)
java·jvm·面试·八股·大厂实习
星核0penstarry2 小时前
企业 API 向后兼容实战:版本控制、废弃字段通知与灰度发布策略
人工智能·后端·api·接口隔离原则·版本控制·架构设计·后端架构
养军博客2 小时前
spirngSecurity 鉴权教程02
java·springsecurity
CoderYanger2 小时前
Java EE 进阶:5. Spring IoC&DI(第二弹):Spring IoC
java·开发语言·spring boot·spring·面试·职场和发展·java-ee
用户别睡觉2 小时前
自己搭的中文 PDF RAG 接了 Redis 缓存、跑了 RAGAS,以为能写“提速多少、准确率多少”,结果两个都没按预期来。
后端
彭亚川Allen2 小时前
985 在职研究生到底怎么样?是不是水硕?是不是.....?
前端·后端·程序员
乘风2483 小时前
# 我做了个会遗忘的 AI 记忆,召回率反而从 8% 涨到 100%
后端
Rain的Java大神之路3 小时前
面试被LeetCode 27(移除元素)问懵?别再用两层 for 循环了:一道“简单题”吃透双指针原地删除,附面试加分话术 + 11 个避坑清单
后端·leetcode·面试