說在前面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
說到最後
本次源碼解析僅表明我的觀點,僅供參考。