springmvc源碼解析MvcNamespaceHandler之視圖配置器和跨域配置

說在前面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

 

說到最後

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

相關文章
相關標籤/搜索