說在前面web
本次主要介紹springmvc配置解析<mvc:freemarker-configurer/>、<mvc:velocity-configurer/>、 <mvc:cors>。關注「天河聊技術」更多中間件源碼解析。spring
springmvc配置解析跨域
本次介紹MvcNamespaceHandler。mvc
進入到這個方法org.springframework.web.servlet.config.FreeMarkerConfigurerBeanDefinitionParser#doParseapp
@Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { // 解析template-loader-path屬性值 List<Element> childElements = DomUtils.getChildElementsByTagName(element, "template-loader-path"); if (!childElements.isEmpty()) { List<String> locations = new ArrayList<String>(childElements.size()); for (Element childElement : childElements) { // 解析location屬性值 locations.add(childElement.getAttribute("location")); } if (locations.isEmpty()) { // 視圖文件前綴 locations.add("/WEB-INF/"); } builder.addPropertyValue("templateLoaderPaths", StringUtils.toStringArray(locations)); } }
進入到這個方法org.springframework.web.servlet.config.VelocityConfigurerBeanDefinitionParser#postProcesscors
@Override protected void postProcess(BeanDefinitionBuilder builder, Element element) { if (!builder.getBeanDefinition().hasAttribute("resourceLoaderPath")) { // 默認視圖路徑 builder.getBeanDefinition().setAttribute("resourceLoaderPath", "/WEB-INF/"); } }
進入到這個方法org.springframework.web.servlet.config.CorsBeanDefinitionParser#parseide
@Override public BeanDefinition parse(Element element, ParserContext parserContext) { Map<String, CorsConfiguration> corsConfigurations = new LinkedHashMap<String, CorsConfiguration>(); // 解析映射 List<Element> mappings = DomUtils.getChildElementsByTagName(element, "mapping"); if (mappings.isEmpty()) { // 添加容許的默認值 -> CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues(); // 若是是空,全部路徑都支持跨域 corsConfigurations.put("/**", config); } else { for (Element mapping : mappings) { CorsConfiguration config = new CorsConfiguration(); // 容許跨的域 if (mapping.hasAttribute("allowed-origins")) { String[] allowedOrigins = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-origins"), ","); config.setAllowedOrigins(Arrays.asList(allowedOrigins)); } // 容許跨域的方法 if (mapping.hasAttribute("allowed-methods")) { String[] allowedMethods = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-methods"), ","); config.setAllowedMethods(Arrays.asList(allowedMethods)); } // 容許跨域的headers if (mapping.hasAttribute("allowed-headers")) { String[] allowedHeaders = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-headers"), ","); config.setAllowedHeaders(Arrays.asList(allowedHeaders)); } // 暴露的headers if (mapping.hasAttribute("exposed-headers")) { String[] exposedHeaders = StringUtils.tokenizeToStringArray(mapping.getAttribute("exposed-headers"), ","); config.setExposedHeaders(Arrays.asList(exposedHeaders)); } // 容許的憑證 if (mapping.hasAttribute("allow-credentials")) { config.setAllowCredentials(Boolean.parseBoolean(mapping.getAttribute("allow-credentials"))); } if (mapping.hasAttribute("max-age")) { config.setMaxAge(Long.parseLong(mapping.getAttribute("max-age"))); } corsConfigurations.put(mapping.getAttribute("path"), config.applyPermitDefaultValues()); } }
進入到這個方法org.springframework.web.cors.CorsConfiguration#applyPermitDefaultValuespost
public CorsConfiguration applyPermitDefaultValues() { if (this.allowedOrigins == null) { this.addAllowedOrigin(ALL); } if (this.allowedMethods == null) { this.setAllowedMethods(Arrays.asList( HttpMethod.GET.name(), HttpMethod.HEAD.name(), HttpMethod.POST.name())); } if (this.allowedHeaders == null) { this.addAllowedHeader(ALL); } if (this.allowCredentials == null) { this.setAllowCredentials(true); } if (this.maxAge == null) { this.setMaxAge(1800L); } return this; }
進入到這個方法org.springframework.web.servlet.config.MvcNamespaceUtils#registerCorsConfigurationsui
public static RuntimeBeanReference registerCorsConfigurations( Map<String, CorsConfiguration> corsConfigurations, ParserContext context, Object source) { // mvcCorsConfigurations 跨域支持bean定義解析 if (!context.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) { RootBeanDefinition corsDef = new RootBeanDefinition(LinkedHashMap.class); corsDef.setSource(source); corsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); if (corsConfigurations != null) { corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations); } // 註冊mvcCorsConfigurations bean定義 context.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsDef); context.registerComponent(new BeanComponentDefinition(corsDef, CORS_CONFIGURATION_BEAN_NAME)); } else if (corsConfigurations != null) { BeanDefinition corsDef = context.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME); corsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations); } return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME); }
往上返回到這個方法org.springframework.web.servlet.config.CorsBeanDefinitionParser#parsethis
說到最後
本次源碼解析僅表明我的觀點,僅供參考。