@EnableWebMvc帮我们做了什么

397 阅读2分钟

@EnableWebMvc

介绍:

  1. 将此注解添加到类中会从 WebMvcConfigurationSupport 导入 Spring MVC 配置

  2. 要自定义导入的配置,请实现接口WebMvcConfigurer并覆盖各个方法

  3. 只有一个类可以具有导入@EnalbeWebMVc注解。但是,可以实现有多个类实现WebMvcConfigurer以自定义提供的配置

它只帮我们导入了DelegatingWebMvcConfiguration类,所以把这个类分析明白即可。

 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.TYPE)
 @Documented
 @Import(DelegatingWebMvcConfiguration.class) //导入DelegatingWebMvcConfiguration类
 public @interface EnableWebMvc {
 }

DelegatingWebMvcConfiguration

主要是将MVC相关的配置委托给一组WebMvcConfigurer实现。

 @Configuration(proxyBeanMethods = false)
 public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
 ​
     // WebMvcConfigurer组合器
     private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
 ​
 ​
     // 拿到容器中全部的 WebMvcConfigurer,并存到 WebMvcConfigurerComposite 类里面
     @Autowired(required = false)
     public void setConfigurers(List<WebMvcConfigurer> configurers) {
         if (!CollectionUtils.isEmpty(configurers)) {
             this.configurers.addWebMvcConfigurers(configurers);
         }
     }
 ​
     // 剩下的所有方法都是这样的:
     // 遍历容器中所有的 WebMvcConfigurer,调用其configureXxx()、addXxx()来读取我们用户自定义的配置
     @Override
     protected void configurePathMatch(PathMatchConfigurer configurer) {
         this.configurers.configurePathMatch(configurer);
     }
     
     protected void addInterceptors(InterceptorRegistry registry) {
         this.configurers.addInterceptors(registry);
     }
     ...
 }

WebMvcConfigurationSupport

这个类帮我们往容器中导入了一堆组件:PathMatchConfigurerContentNegotiationManagerHandlerMethodArgumentResolverHandlerMethodReturnValueHandlerHttpMessageConverterCorsConfigurationAsyncSupportConfigurer

具体的可以参照此类上的文档注释或官网的API文档

 public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {
 ​
     // RequestMappingHandlerMapping
     @Bean
     public RequestMappingHandlerMapping requestMappingHandlerMapping(
         @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
         @Qualifier("mvcConversionService") FormattingConversionService conversionService,
         @Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
 ​
         RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
         
         // 省略代码
         ...
 ​
         return mapping;
     }
     
     
     // 内容协商管理器
     @Bean
     public ContentNegotiationManager mvcContentNegotiationManager() {
         if (this.contentNegotiationManager == null) {
             ContentNegotiationConfigurer configurer = new ContentNegotiationConfigurer(this.servletContext);
             configurer.mediaTypes(getDefaultMediaTypes());
             configureContentNegotiation(configurer);
             this.contentNegotiationManager = configurer.buildContentNegotiationManager();
         }
         return this.contentNegotiationManager;
     }
     
     // RequestMappingHandlerAdapter
     @Bean
     public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
         @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
         @Qualifier("mvcConversionService") FormattingConversionService conversionService,
         @Qualifier("mvcValidator") Validator validator) {
 ​
         RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
 ​
         // 省略代码
         ...
 ​
         return adapter;
     }
     
     // 转换器服务:Converter and/or Formatter
     @Bean
     public FormattingConversionService mvcConversionService() {
         FormattingConversionService conversionService = new DefaultFormattingConversionService();
         addFormatters(conversionService);
         return conversionService;
     }
     
     // 校验器
     @Bean
     public Validator mvcValidator() {
         Validator validator = getValidator();
 ​
         // 省略代码
         ...
             
         return validator;
     }
     
     // 处理器异常解析器
     @Bean
     public HandlerExceptionResolver handlerExceptionResolver(
         @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
         List<HandlerExceptionResolver> exceptionResolvers = new ArrayList<>();
 ​
         // 省略代码
         ...
             
         return composite;
     }
     
     // 视图解析器
     @Bean
     public ViewResolver mvcViewResolver(
         @Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
         ViewResolverRegistry registry =
             new ViewResolverRegistry(contentNegotiationManager, this.applicationContext);
 ​
         // 省略代码
         ...
 ​
         ViewResolverComposite composite = new ViewResolverComposite();
        
         // 省略代码
         ...
             
         return composite;
     }
 }

总结

@EnableWebMvc的作用

  1. 帮我们往容器中注册了一些SpringMVC必要的组件。如:处理器适配器、处理器映射、...

  2. 拿到我们自定义的WebMvcConfigurer配置类,读取我们自定义的配置

类图

image.png

  • DelegatingWebMvcConfiguration:会拿到容器中所有的WebMvcConfigurer类,然后依次调用其方法进行配置

  • WebMvcConfigurationSupport:它给容器中导入了一堆组件;并且提供了允许用户自定义配置的方法

  • WebMvcConfigurerComposite:也是一个WebMvcConfigurer,这个类封装了容器中所有的WebMvcConfigurer。以便后续使用

  • WebMvcConfigurer:SpringMVC留给我们的定义底层行为的入口。我们可以通过重写这个类里的方法来自定义配置,定义底层行为