`
357029540
  • 浏览: 737317 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论
阅读更多

    前面说完我们如何从github上面去取数据,这里说说server端剩余的类。ConfigServerEncryptionConfiguration类。从类的名字我们可以看出主要是加解密相关的配置类,进入类中可以看到定义了EncryptionController encryptionController()这个的bean,直接进入到EncryptionController类,controller类的访问路径可以通过spring.cloud.config.server.prefix属性进行配置,在类中我们可以看到一系列的加解密相关操作的端点,这里就不在具体介绍,可以参考代码查看。需要注意的是使用的是加密算法是AES256加密,由于jdk默认提供的是AES128的方式,所以需要去http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html下载相关jar包,这里指的是jdk1.8,下载解压后覆盖\jre\lib\security路径下的解压后得到的jar包就可以了。

     在看下EncryptionAutoConfiguration类,进入该类,我们可以了解到这里定义了2个静态内部类和2个一般内部类,分别是EncryptorConfigurationKeyStoreConfigurationSingleTextEncryptorConfigurationDefaultTextEncryptorConfiguration

EncryptorConfiguration类中定义了在prefix是spring.cloud.config.server.encrypt.enabled

true的条件下才能有效注入加解密的代码;KeyStoreConfiguration这个类主要是用于对称加密的存储;SingleTextEncryptorConfiguration这个类有效的情况是存在TextEncryptorbean和不存在TextEncryptorLocatorbean时,这个时候才会初始化里面的beanDefaultTextEncryptorConfiguration这个类有效的情况是不存在TextEncryptorbean才会初始化里面的bean。所以整体上来说EncryptionAutoConfiguration类主要是为加解密初始化bean的操作。

  说完server端的一些内部使用,但是我们外部如何来调用,接下来我们看看EnvironmentController和ResourceController这2个controller类的使用。

  首先说说ResourceController类,进入到这个controller可以看到它是一个restful controller类,入口地址可以通过prefix为spring.cloud.config.server.prefix来定义总的入口,类中定义了3个RequestMapping

 

 1.@RequestMapping("/{name}/{profile}/{label}/**")

  

@RequestMapping("/{name}/{profile}/{label}/**")
public String retrieve(@PathVariable String name, @PathVariable String profile,
      @PathVariable String label, HttpServletRequest request,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws IOException {
   String path = getFilePath(request, name, profile, label);
   return retrieve(name, profile, label, path, resolvePlaceholders);
}

     从路径上看它必须匹配有3个及以上的参数,返回类型是String字符串,在getFilePath()方法里面可以看到一系列的替换操作,这里不贴出代码了,进入到retrieve()方法

synchronized String retrieve(String name, String profile, String label, String path,
      boolean resolvePlaceholders) throws IOException {
   if (name != null && name.contains("(_)")) {
      // "(_)" is uncommon in a git repo name, but "/" cannot be matched
      // by Spring MVC
      name = name.replace("(_)", "/");
   }
   if (label != null && label.contains("(_)")) {
      // "(_)" is uncommon in a git branch name, but "/" cannot be matched
      // by Spring MVC
      label = label.replace("(_)", "/");
   }

   // ensure InputStream will be closed to prevent file locks on Windows
   try (InputStream is = this.resourceRepository.findOne(name, profile, label, path)
         .getInputStream()) {
      String text = StreamUtils.copyToString(is, Charset.forName("UTF-8"));
      if (resolvePlaceholders) {
         Environment environment = this.environmentRepository.findOne(name,
               profile, label);
         text = resolvePlaceholders(prepareEnvironment(environment), text);
      }
      return text;
   }
}

 该方法是一个synchronized方法,首先做的是一些替换操作,然后进入到ResourceRepository接口的实现类GenericResourceRepository中的findOne()方法

public synchronized Resource findOne(String application, String profile, String label,
      String path) {
   String[] locations = this.service.getLocations(application, profile, label).getLocations();
   try {
      for (int i = locations.length; i-- > 0;) {
         String location = locations[i];
         for (String local : getProfilePaths(profile, path)) {
            Resource file = this.resourceLoader.getResource(location)
                  .createRelative(local);
            if (file.exists() && file.isReadable()) {
               return file;
            }
         }
      }
   }
   catch (IOException e) {
      throw new NoSuchResourceException(
            "Error : " + path + ". (" + e.getMessage() + ")");
   }
   throw new NoSuchResourceException("Not found: " + path);
}

 

private Collection<String> getProfilePaths(String profiles, String path) {
   Set<String> paths = new LinkedHashSet<>();
   for (String profile : StringUtils.commaDelimitedListToSet(profiles)) {
      if (!StringUtils.hasText(profile) || "default".equals(profile)) {
         paths.add(path);
      }
      else {
         String ext = StringUtils.getFilenameExtension(path);
         String file = path;
         if (ext != null) {
            ext = "." + ext;
            file = StringUtils.stripFilenameExtension(path);
         }
         else {
            ext = "";
         }
         paths.add(file + "-" + profile + ext);
      }
   }
   paths.add(path);
   return paths;
}

 从实现上可以发现它也是一个synchronized方法,它首先会根据初始化的配置文件去SearchPathLocator接口的实现类去数组locations,它主要就是从配置来源做一些获取配置文件到本地的操作,可以通过前面介绍的git相关类参考,然后根据路径返回配置文件信息,返回到retrieve()方法中后,去除一些不必要的信息以及清除占位符之类的后返回String格式的text。

 

2.@RequestMapping(value = "/{name}/{profile}/**", params = "useDefaultLabel")

@RequestMapping(value = "/{name}/{profile}/**", params = "useDefaultLabel")
public String retrieve(@PathVariable String name, @PathVariable String profile,
      HttpServletRequest request,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws IOException {
   String path = getFilePath(request, name, profile, null);
   return retrieve(name, profile, null, path, resolvePlaceholders);
}

 这个请求基本和上面的请求差不多,范围稍微大一些,但是必须包含特定参数useDefaultLabel,其他处理过程一样。

 

3.@RequestMapping(value = "/{name}/{profile}/{label}/**", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)

@RequestMapping(value = "/{name}/{profile}/{label}/**", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public synchronized byte[] binary(@PathVariable String name,
      @PathVariable String profile, @PathVariable String label,
      HttpServletRequest request) throws IOException {
   String path = getFilePath(request, name, profile, label);
   return binary(name, profile, label, path);
}

 这个请求类的路径也是和前面的差不多,但是必须包含返回的类型produces参数为MediaType.APPLICATION_OCTET_STREAM_VALUE的数据,在binary()方法中,其基本方法与前面的mapping路径一样,唯一不同就是把获取到的文件信息直接转为byte[]数组。

 我们接下来看看EnvironmentController类,进入到这个controller可以看到它是一个restful controller类,入口地址可以通过prefix为spring.cloud.config.server.prefix来定义总的入口,类中定义了8个RequestMapping。

 

1.@RequestMapping("/{name}/{profiles:.*[^-].*}")

@RequestMapping("/{name}/{profiles:.*[^-].*}")
public Environment defaultLabel(@PathVariable String name,
      @PathVariable String profiles) {
   return labelled(name, profiles, null);
}

 通过mapping可以看到它的请求路径是不含label且不能带有-的路径,而labelled()方法在下面的mapping中介绍,返回类型是一个Environment对象

 

2.@RequestMapping("/{name}/{profiles}/{label:.*}")

@RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(@PathVariable String name, @PathVariable String profiles,
      @PathVariable String label) {
   if (name != null && name.contains("(_)")) {
      // "(_)" is uncommon in a git repo name, but "/" cannot be matched
      // by Spring MVC
      name = name.replace("(_)", "/");
   }
   if (label != null && label.contains("(_)")) {
      // "(_)" is uncommon in a git branch name, but "/" cannot be matched
      // by Spring MVC
      label = label.replace("(_)", "/");
   }
   Environment environment = this.repository.findOne(name, profiles, label);
   if(!acceptEmpty && (environment == null || environment.getPropertySources().isEmpty())){
       throw new EnvironmentNotFoundException("Profile Not found");
   }
   return environment;
}

 这个路径将接收全部类型的后缀包含路径为name,profileslabel的路径参数,方法中首先做了一些替换操作,然后通过调用具体的EnvironmentRepository接口的实现类方法findOne()去查找配置文件,具体可以参考前面提到的MultipleJGitEnvironmentRepository的实现,获取到Environment后就返回。在client端,我们就会调用这个接口方法进行远程配置数据的更新操作。

 

3.@RequestMapping("/{name}-{profiles}.properties")

@RequestMapping("/{name}-{profiles}.properties")
public ResponseEntity<String> properties(@PathVariable String name,
      @PathVariable String profiles,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws IOException {
   return labelledProperties(name, profiles, null, resolvePlaceholders);
}

 这个路径是直接获取没有label且配置文件后缀为properties的信息,labelledProperties()方法将在下面介绍。

 

4.@RequestMapping("/{label}/{name}-{profiles}.properties")

@RequestMapping("/{label}/{name}-{profiles}.properties")
public ResponseEntity<String> labelledProperties(@PathVariable String name,
      @PathVariable String profiles, @PathVariable String label,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws IOException {
   validateProfiles(profiles);
   Environment environment = labelled(name, profiles, label);
   Map<String, Object> properties = convertToProperties(environment);
   String propertiesString = getPropertiesString(properties);
   if (resolvePlaceholders) {
      propertiesString = resolvePlaceholders(prepareEnvironment(environment),
            propertiesString);
   }
   return getSuccess(propertiesString);
}

 这个路径是直接获取包含label且配置文件后缀为properties的信息,首先校验了profiles路径是否包含了-,如果包含了直接返回错误,然后直接去labelled()方法获取Environment对象,就是第二个请求路径的方法,最后就是一系列的组装解析数据的过程。

 

5.@RequestMapping("{name}-{profiles}.json")

@RequestMapping("{name}-{profiles}.json")
public ResponseEntity<String> jsonProperties(@PathVariable String name,
      @PathVariable String profiles,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws Exception {
   return labelledJsonProperties(name, profiles, null, resolvePlaceholders);
}

 这个路径是直接获取没有label且配置文件后缀为json的信息,labelledJsonProperties()方法将在下面介绍。

 

6.@RequestMapping("/{label}/{name}-{profiles}.json")

@RequestMapping("/{label}/{name}-{profiles}.json")
public ResponseEntity<String> labelledJsonProperties(@PathVariable String name,
      @PathVariable String profiles, @PathVariable String label,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws Exception {
   validateProfiles(profiles);
   Environment environment = labelled(name, profiles, label);
   Map<String, Object> properties = convertToMap(environment);
   String json = this.objectMapper.writeValueAsString(properties);
   if (resolvePlaceholders) {
      json = resolvePlaceholders(prepareEnvironment(environment), json);
   }
   return getSuccess(json, MediaType.APPLICATION_JSON);
}

 从方法实现上看validateProfiles()方法和labelled()方法和前面一样,然后将Environment对象进行map转换,然后通过ObjectMapper进行转换,之后去除掉不必要的参数,用MediaType.APPLICATION_JSON的方式返回。

 

7.@RequestMapping({ "/{name}-{profiles}.yml", "/{name}-{profiles}.yaml" })

@RequestMapping({ "/{name}-{profiles}.yml", "/{name}-{profiles}.yaml" })
public ResponseEntity<String> yaml(@PathVariable String name,
      @PathVariable String profiles,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws Exception {
   return labelledYaml(name, profiles, null, resolvePlaceholders);
}

 这个路径对应两种配置文件路径且不包含label,labelledYaml()方法将在下面介绍。

 

8.@RequestMapping({ "/{label}/{name}-{profiles}.yml",
      "/{label}/{name}-{profiles}.yaml" })

@RequestMapping({ "/{label}/{name}-{profiles}.yml",
      "/{label}/{name}-{profiles}.yaml" })
public ResponseEntity<String> labelledYaml(@PathVariable String name,
      @PathVariable String profiles, @PathVariable String label,
      @RequestParam(defaultValue = "true") boolean resolvePlaceholders)
      throws Exception {
   validateProfiles(profiles);
   Environment environment = labelled(name, profiles, label);
   Map<String, Object> result = convertToMap(environment);
   if (this.stripDocument && result.size() == 1
         && result.keySet().iterator().next().equals("document")) {
      Object value = result.get("document");
      if (value instanceof Collection) {
         return getSuccess(new Yaml().dumpAs(value, Tag.SEQ, FlowStyle.BLOCK));
      }
      else {
         return getSuccess(new Yaml().dumpAs(value, Tag.STR, FlowStyle.BLOCK));
      }
   }
   String yaml = new Yaml().dumpAsMap(result);

   if (resolvePlaceholders) {
      yaml = resolvePlaceholders(prepareEnvironment(environment), yaml);
   }

   return getSuccess(yaml);
}

 从方法实现上看validateProfiles()方法和labelled()方法和前面一样,然后就是就行yml相关的操作,这里不详述了。

以上就主要介绍完了spring-cloud-config-server端的源码。

 

  • 大小: 21.8 KB
0
0
分享到:
评论

相关推荐

    基于spring cloud项目源码源码.rar

    《Spring Cloud项目源码深度解析》 在当前的微服务架构领域,Spring Cloud以其强大的功能和易用性,成为开发者构建分布式系统的重要选择。本文将深入探讨基于Spring Cloud的项目源码,帮助读者理解其核心原理,提升...

    尚硅谷SpringCloud视频 + 源码 百度网盘

    ### 一、SpringCloud简介与核心组件 #### 1.1 SpringCloud概述 SpringCloud是一套基于Spring Boot实现的微服务云应用开发工具集,它提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线...

    spring cloud 配置源码.zip

    《Spring Cloud配置源码解析与实战》 Spring Cloud作为微服务架构的重要组件,为开发者提供了在分布式系统(如配置管理、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话...

    spring-cloud实战源码

    本教程将从基础入手,逐步深入到源码解析,使读者能更深入地了解和运用Spring Cloud。 首先,我们从入门开始。Spring Cloud提供了一个快速构建分布式系统工具集,包括服务发现(Eureka)、配置中心(Config Server...

    springcloud 源码+解读

    1. **SpringCloud源码解析**: SpringCloud的源码分析有助于开发者了解其实现机制,从而更好地定制和优化自己的服务。源码中包含了Eureka服务发现、Zuul边缘服务、Hystrix断路器、 Ribbon客户端负载均衡、Feign声明...

    尚硅谷SpringCloud的源码及思维导图

    总的来说,通过尚硅谷的SpringCloud源码解析和思维导图,开发者不仅可以深入了解SpringCloud的运作原理,还能提升对微服务架构设计的理解,为实际项目开发提供有力的支持。同时,对源码的学习也有助于培养解决问题和...

    SpringCloud源码-01.zip

    《SpringCloud源码解析——构建微服务架构的关键组件》 SpringCloud作为当今最热门的微服务框架之一,深受广大开发者喜爱。它集成了众多优秀的开源项目,为开发人员提供了便捷的微服务开发工具。本篇将围绕Spring...

    springcloud-config-master.rar

    《SpringCloud Config 源码解析与应用实践》 SpringCloud Config 是一个强大的微服务配置中心,它允许我们在运行时管理应用的配置,并且能够实时地推送到客户端。本篇文章将深入探讨 SpringCloud Config 的核心原理...

    基于springcloud的电商平台源码.zip

    《基于SpringCloud的电商平台源码解析》 在现代互联网应用开发中,微服务架构已经成为主流。Spring Cloud作为一套完整的微服务解决方案,为开发者提供了构建分布式系统所需的工具集合,包括服务发现、配置中心、...

    适合新手入门的springcloud完整项目资源,附带sql和详细的开发文档,可直接导入运行。

    本资源为新手提供了一个完整的SpringCloud入门项目,包括源码、SQL脚本和详细的开发文档,非常适合想要快速了解和学习SpringCloud的新手。 1. **SpringCloud简介** SpringCloud是基于SpringBoot构建的服务治理框架...

    基于springcloud的分布式网上商城系统源码.zip

    《基于SpringCloud的分布式网上商城系统源码解析》 在当今互联网时代,电子商务系统的复杂性和规模日益增大,传统的单体架构难以应对高并发、高可用的业务需求。为了解决这些问题,开发人员开始转向分布式系统架构...

    SpringCloud黑马商城后端代码

    本篇文章将深入探讨“SpringCloud黑马商城后端代码”,解析其中的关键技术和实现细节。 首先,Spring Cloud是基于Spring Boot的一套微服务解决方案,它提供了服务注册与发现、配置中心、API网关、负载均衡、熔断器...

    springcloud学习源码-yuanma.zip

    本篇将深入探讨Spring Cloud的核心组件和原理,结合"springcloud学习源码-yuanma.zip"中的源码,为你带来一次全面的学习体验。 首先,我们来了解Spring Cloud的基础知识。Spring Cloud是基于Spring Boot的微服务...

    2020最新版SpringCloud(H版&alibaba)框架开发教程全套完整版从入门到精通(41-80讲).rar

    《2020最新版SpringCloud(H版&alibaba)框架开发教程》是一套全面而深入的SpringCloud学习资源,涵盖了从基础到高级的各种技术点。这套教程旨在帮助开发者掌握SpringCloud的核心概念和实践技巧,尤其针对H版及阿里...

    <>源代码

    《SpringCloud微服务实战》这本书籍的源代码包含了大量的实践示例和配置,旨在帮助读者深入理解并掌握Spring Cloud在实际开发中的应用。Spring Cloud是一个基于Spring Boot实现的服务发现、配置管理和API网关等...

    springcloud的所有技能都在这里面了

    总的来说,这份"Spring Cloud.pdf"学习资料涵盖了Spring Cloud的基础知识、核心组件的使用、源码解析以及实战演示,对于想要深入学习和掌握Spring Cloud的开发者来说是一份宝贵的资源。通过系统学习并实践其中的示例...

    从零开始搭建SpringCloud第七节源码

    源码解析可以帮助我们理解Zuul如何处理请求,以及过滤器链的执行流程。 3. **断路器** - Hystrix是Netflix开源的断路器库,用于防止服务雪崩。当服务调用失败或响应时间过长时,断路器会打开,避免后续请求继续失败...

    spring cloud实战项目

    1. 配置中心:可能使用了Spring Cloud Config来集中管理所有服务的配置,这样可以方便地在不同环境中切换配置。 2. 服务注册与发现:可能使用Eureka或Consul等服务注册与发现组件,确保服务之间的通信。 3. 安全配置...

    疯狂springCloud实战架构

    《疯狂springCloud实战架构》是针对企业级分布式应用开发的一款强大框架——Spring Cloud的深度解析与实战指南。Spring Cloud作为微服务生态中的重要组件,它为开发者提供了在分布式系统(如配置管理、服务发现、...

    springCloud

    断路器示意图 SpringCloud Netflix实现了断路器库的名字叫Hystrix. 在微服务架构下,通常会有多个层次的服务调用. 下面是微服架构下, 浏览器端通过API访问后台微服务的一个示意图: hystrix 1 一个微服务的超时...

Global site tag (gtag.js) - Google Analytics