springmvc源碼解析之@EnableWebMvc一

說在前面web

本次介紹MvcNamespaceHandler。關注「天河聊架構」微信公衆號更多源碼解析。spring

 

springmvc配置解析json

@EnableWebMvc這個註解幹了什麼,初始化RequestMappingHandlerMapping跨域

先看下這個註解源碼服務器

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

直接找到這個類org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport微信

找到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerMapping 初始化RequestMappingHandlerMapping架構

@Bean
   public RequestMappingHandlerMapping requestMappingHandlerMapping() {
//    建立RequestMappingHandlerMapping -》
      RequestMappingHandlerMapping mapping = createRequestMappingHandlerMapping();
      mapping.setOrder(0);
//    初始化攔截器 -》
      mapping.setInterceptors(getInterceptors());
//    設置媒體類型管理器 -》
      mapping.setContentNegotiationManager(mvcContentNegotiationManager());
//    跨域配置 -》
      mapping.setCorsConfigurations(getCorsConfigurations());
//    獲取路徑匹配配置器 -》
      PathMatchConfigurer configurer = getPathMatchConfigurer();
//    開啓前綴匹配
      Boolean useSuffixPatternMatch = configurer.isUseSuffixPatternMatch();
      if (useSuffixPatternMatch != null) {
         mapping.setUseSuffixPatternMatch(useSuffixPatternMatch);
      }
      Boolean useRegisteredSuffixPatternMatch = configurer.isUseRegisteredSuffixPatternMatch();
      if (useRegisteredSuffixPatternMatch != null) {
         mapping.setUseRegisteredSuffixPatternMatch(useRegisteredSuffixPatternMatch);
      }
//    開啓後綴匹配
      Boolean useTrailingSlashMatch = configurer.isUseTrailingSlashMatch();
      if (useTrailingSlashMatch != null) {
         mapping.setUseTrailingSlashMatch(useTrailingSlashMatch);
      }

//    獲取url路徑適配器
      UrlPathHelper pathHelper = configurer.getUrlPathHelper();
      if (pathHelper != null) {
         mapping.setUrlPathHelper(pathHelper);
      }
//    獲取路徑匹配器
      PathMatcher pathMatcher = configurer.getPathMatcher();
      if (pathMatcher != null) {
         mapping.setPathMatcher(pathMatcher);
      }

      return mapping;
   }

進入到這個方法org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#afterPropertiesSetmvc

@Override
   public void afterPropertiesSet() {
      this.config = new RequestMappingInfo.BuilderConfiguration();
//    設置url路徑解析器
      this.config.setUrlPathHelper(getUrlPathHelper());
//    設置路徑匹配器
      this.config.setPathMatcher(getPathMatcher());
//    設置前綴路徑匹配器
      this.config.setSuffixPatternMatch(this.useSuffixPatternMatch);
//    設置後綴路徑匹配器
      this.config.setTrailingSlashMatch(this.useTrailingSlashMatch);
//    註冊路徑前綴匹配器
      this.config.setRegisteredSuffixPatternMatch(this.useRegisteredSuffixPatternMatch);
//    設置媒體類型管理器
      this.config.setContentNegotiationManager(getContentNegotiationManager());
//-》
      super.afterPropertiesSet();
   }

進入到這個方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#initHandlerMethodsapp

protected void initHandlerMethods() {
      if (logger.isDebugEnabled()) {
         logger.debug("Looking for request mappings in application context: " + getApplicationContext());
      }
      String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
            BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
            getApplicationContext().getBeanNamesForType(Object.class));
      for (String beanName : beanNames) {
         if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
            Class<?> beanType = null;
            try {
               beanType = getApplicationContext().getType(beanName);
            }
            catch (Throwable ex) {
               // An unresolvable bean type, probably from a lazy bean - let's ignore it.
               if (logger.isDebugEnabled()) {
                  logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
               }
            }
            if (beanType != null && isHandler(beanType)) {
               detectHandlerMethods(beanName);
            }
         }
      }
//    獲取handlerMethod並初始化
      handlerMethodsInitialized(getHandlerMethods());
   }

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getInterceptorscors

protected final Object[] getInterceptors() {
      if (this.interceptors == null) {
//       建立攔截器註冊器
         InterceptorRegistry registry = new InterceptorRegistry();
//       mvc配置器添加攔截器註冊器 -》
         addInterceptors(registry);
//       添加ConversionServiceExposingInterceptor 攔截器 -》
         registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));
//       添加ResourceUrlProviderExposingInterceptor 攔截器 -》
         registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));
//       從攔截器註冊器中獲取攔截器 -》
         this.interceptors = registry.getInterceptors();
      }
      return this.interceptors.toArray();
   }

進入到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addInterceptors

@Override
protected void addInterceptors(InterceptorRegistry registry) {
   this.configurers.addInterceptors(registry);
}

進入到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcConversionService

@Bean
   public FormattingConversionService mvcConversionService() {
//    初始化默認轉換服務
      FormattingConversionService conversionService = new DefaultFormattingConversionService();
//    添加格式化器 -》
      addFormatters(conversionService);
      return conversionService;
   }

進入到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addFormatters

@Override
protected void addFormatters(FormatterRegistry registry) {
   this.configurers.addFormatters(registry);
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcResourceUrlProvider

@Bean
   public ResourceUrlProvider mvcResourceUrlProvider() {
//    初始化資源url服務器
      ResourceUrlProvider urlProvider = new ResourceUrlProvider();
//    獲取url路徑解析器 -》
      UrlPathHelper pathHelper = getPathMatchConfigurer().getUrlPathHelper();
      if (pathHelper != null) {
         urlProvider.setUrlPathHelper(pathHelper);
      }
      PathMatcher pathMatcher = getPathMatchConfigurer().getPathMatcher();
      if (pathMatcher != null) {
         urlProvider.setPathMatcher(pathMatcher);
      }
      return urlProvider;
   }

進入到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getPathMatchConfigurer

protected PathMatchConfigurer getPathMatchConfigurer() {
   if (this.pathMatchConfigurer == null) {
      this.pathMatchConfigurer = new PathMatchConfigurer();
      configurePathMatch(this.pathMatchConfigurer);
   }
   return this.pathMatchConfigurer;
}

進入到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configurePathMatch

@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
   this.configurers.configurePathMatch(configurer);
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.InterceptorRegistry#getInterceptors

protected List<Object> getInterceptors() {
      List<Object> interceptors = new ArrayList<Object>(this.registrations.size());
      for (InterceptorRegistration registration : this.registrations) {
//       獲取攔截器 -》
         interceptors.add(registration.getInterceptor());
      }
      return interceptors ;
   }

進入到這個方法org.springframework.web.servlet.config.annotation.InterceptorRegistration#getInterceptor

protected Object getInterceptor() {
      if (this.includePatterns.isEmpty() && this.excludePatterns.isEmpty()) {
         return this.interceptor;
      }

//    解析包含路徑
      String[] include = StringUtils.toStringArray(this.includePatterns);
//    解析排除路徑
      String[] exclude = StringUtils.toStringArray(this.excludePatterns);
      MappedInterceptor mappedInterceptor = new MappedInterceptor(include, exclude, this.interceptor);
      if (this.pathMatcher != null) {
         mappedInterceptor.setPathMatcher(this.pathMatcher);
      }
      return mappedInterceptor;
   }

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#mvcContentNegotiationManager

進入到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getDefaultMediaTypes

protected Map<String, MediaType> getDefaultMediaTypes() {
   Map<String, MediaType> map = new HashMap<String, MediaType>(4);
   if (romePresent) {
      map.put("atom", MediaType.APPLICATION_ATOM_XML);
      map.put("rss", MediaType.APPLICATION_RSS_XML);
   }
   if (jaxb2Present || jackson2XmlPresent) {
      map.put("xml", MediaType.APPLICATION_XML);
   }
   if (jackson2Present || gsonPresent) {
      map.put("json", MediaType.APPLICATION_JSON);
   }
   return map;
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configureContentNegotiation

@Override
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
   this.configurers.configureContentNegotiation(configurer);
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer#buildContentNegotiationManager

protected ContentNegotiationManager buildContentNegotiationManager() {
//    添加媒體類型
      this.factory.addMediaTypes(this.mediaTypes);
//    等待ContentNegotiationManagerFactoryBean初始化配置
      this.factory.afterPropertiesSet();
      return this.factory.getObject();
   }

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getCorsConfigurations

protected final Map<String, CorsConfiguration> getCorsConfigurations() {
      if (this.corsConfigurations == null) {
//       初始化跨域註冊器
         CorsRegistry registry = new CorsRegistry();
//       添加跨域映射 -》
         addCorsMappings(registry);
//       獲取跨域配置 -》
         this.corsConfigurations = registry.getCorsConfigurations();
      }
      return this.corsConfigurations;
   }

進入到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addCorsMappings

@Override
protected void addCorsMappings(CorsRegistry registry) {
   this.configurers.addCorsMappings(registry);
}

進入到這個方法org.springframework.web.servlet.config.annotation.CorsRegistry#getCorsConfigurations

protected Map<String, CorsConfiguration> getCorsConfigurations() {
   Map<String, CorsConfiguration> configs = new LinkedHashMap<String, CorsConfiguration>(this.registrations.size());
   for (CorsRegistration registration : this.registrations) {
      configs.put(registration.getPathPattern(), registration.getCorsConfiguration());
   }
   return configs;
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getPathMatchConfigurer

protected PathMatchConfigurer getPathMatchConfigurer() {
   if (this.pathMatchConfigurer == null) {
      this.pathMatchConfigurer = new PathMatchConfigurer();
      configurePathMatch(this.pathMatchConfigurer);
   }
   return this.pathMatchConfigurer;
}

進入到這個方法org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#configurePathMatch

@Override
protected void configurePathMatch(PathMatchConfigurer configurer) {
   this.configurers.configurePathMatch(configurer);
}

往上返回到這個方法org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerMapping

 

說到最後

本次源碼解析僅表明我的觀點,僅供參考。

相關文章
相關標籤/搜索