【SpringBoot】SpringCloud Config Server实践

  • 概述
  • ConfigServer简单实践
    • 搭建ConfigServer
    • 使用ConfigServer
  • 覆盖配置项
    • 场景
    • 原因分析
    • 解决方案

概述

使用Spring Cloud开发微服务时,ConfigServer是常用的组件,它的作用是将Spring相关的配置项统一起来,其他微服务可以根据实际需要从ConfigServer fetch配置。

本文内容:
1. 部署ConfigServer(配置文件使用native存放而不是git仓库)
2. 如何覆盖ConfigServer中的配置项

ConfigServer简单实践

搭建ConfigServer

首先创建maven project,pom.xml如下


    org.springframework.boot
    spring-boot-starter-parent
    1.4.0.RELEASE


    
        
            org.springframework.cloud
            spring-cloud-dependencies
            Camden.RELEASE
            pom
            import
        
    



    
        org.springframework.cloud
        spring-cloud-config-server
    

application.properties配置如下:

server.port=8888

#使用本地的配置文件
spring.profiles.active=native

上述的配置很简单,直接使用native 来存放配置文件。
然后在resources目录下新建application-datasource-dev.yml

zeus:
  name: commons datasource configs for develop
  version: 1.0

#kafka配置
kafka:
  host: localhost
  port: 9092

#mongodb配置
spring:
  data:
    mongodb:
      database: test
      host: localhost
      port: 27017

#仅输出ERROR日志
logging:
  level:
    com.netflix.discovery.shared.resolver.aws.ConfigClusterResolver: ERROR

接着编写启动类ConfigServerApplication.java

@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

运行项目即可。

使用ConfigServer

在需要用到ConfigServer的项目中,引入

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-configartifactId>
dependency>

然后我想要用application-datasource-dev.yml这个配置文件,则进行如下配置:

spring:
  application:
    name: examples-manager
  cloud:
    #配置服务器
    config:
      uri: http://localhost:${config.port:8888}
      name: application-datasource                  #配置名称
      profile: dev                                  #最后定向到文件:application-datasource-dev.[properties|yml|

覆盖配置项

场景

成功应用ConfigServer的配置后,发现不能对其中的值进行覆盖。比如ConfigServer中database设置为test,但是我在本地项目中想要用test2

此时不管通过何种方法设置database=test2(如命令行、application.properties、application.yml、SystemProperties等)都不能覆盖test这个值。

原因分析

出现上述情况,是因为来自ConfigServer的配置项优先级最高。Spring application中配置项的优先级大致如下:

bootstrapProperties                                             #来自configServer的值
commandLineArgs                                                 #命令行参数
servletConfigInitParams                                         
servletContextInitParams                                        
systemProperties                                                
systemEnvironment                       
random      
applicationConfig: [classpath:/application.yml]
springCloudClientHostInfo
applicationConfig: [classpath:/bootstrap.yml]
defaultProperties
Management Server

上面的排序是通过implements ApplicationListener 然后打印出来的。

通过上面的顺序,我们可以知道,Spring想要得到一个配置的值,就按照上面的顺序一个个去找,找到就直接返回。由于ConfigServer处于最优先级,本地项目不管怎么设置都不能覆盖。

解决方案

方法很简单,我们只需要调整一下优先级顺序即可。直接上代码:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ConfigServicePropertyDeprioritizer
        implements ApplicationListener<ApplicationPreparedEvent> {
    private static final String CONFIG_SOURCE = "bootstrapProperties";

    @Override
    public void onApplicationEvent(ApplicationPreparedEvent event) {
        ConfigurableEnvironment environment = event.getApplicationContext()
                .getEnvironment();
        MutablePropertySources sources = environment.getPropertySources();

        //默认使用applicationConfig级别来进行覆盖
        if(sources.contains(CONFIG_SOURCE)){
            sources.addBefore("defaultProperties", sources.get(CONFIG_SOURCE));
        }
    }
}

直接使用上面的类即可。

你可能感兴趣的:(那年开始的java)