springboot-监听apollo配置

版权声明:转发请注明,谢谢配合 https://blog.csdn.net/qq_31289187/article/details/84346529

一、从apollo读取配置:包括apollo本地搭建和从apollo读取配置的基本方法

二、监听apollo配置

1.1、目的:当我们把一些配置放在apollo中,但是里面有一些可变的配置,由于要测试,或者需求更改,或者其它问题,apollo有的配置总之会修改,如果不加监听apollo配置的方法,我们每次修改配置之后都需要 重启服务,非常麻烦。

2.1、ApolloDemoTestApplication类

package com.cn.dl;

import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;

@SpringBootApplication
@EnableApolloConfig
public class ApolloDemoTestApplication {

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

注意:这里要加上@EnableApolloConfig 注解,否则依赖注入的Config=null

java.lang.IllegalStateException: Failed to execute CommandLineRunner
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:816) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:797) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:324) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	at com.cn.dl.ApolloDemoTestApplication.main(ApolloDemoTestApplication.java:13) [classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) [idea_rt.jar:na]
Caused by: java.lang.NullPointerException: null
	at com.cn.dl.ApolloConfigurationChange.monitorApolloConfigurationChange(ApolloConfigurationChange.java:16) ~[classes/:na]
	at com.cn.dl.InitApolloConfigure.loadCommonConfig(InitApolloConfigure.java:53) ~[classes/:na]
	at com.cn.dl.InitApolloConfigure.run(InitApolloConfigure.java:31) ~[classes/:na]
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:813) [spring-boot-2.1.0.RELEASE.jar:2.1.0.RELEASE]
	... 10 common frames omitted

2.2、PropertiesUtils类

package com.cn.dl;


import java.util.Properties;

/**
 * Created by Tiger on 2018/10/10.
 * 读取公共apollo配置
 */
public class PropertiesUtils {

    public static final String COMMON = "apollo-common";
    public static final Properties properties = new Properties();

    public String getString(String key){
        return properties.getProperty(key);
    }

    public Integer getInteger(String key){
        try {
            return Integer.parseInt(properties.getProperty(key));
        }catch (Exception e){
            return null;
        }
    }
    public Long getLong(String key){
        try {
            return Long.parseLong(properties.getProperty(key));
        }catch (Exception e){
            return null;
        }
    }

    public Boolean getBoolean(String key){
        try {
            return Boolean.parseBoolean(properties.getProperty(key));
        }catch (Exception e){
            return null;
        }
    }
}
public static final String COMMON = "apollo-common";

注意:apollo-common是我自己本地测试的一个公共配置,可有可无

2.3、InitApolloConfigure类:读取配置

package com.cn.dl;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfig;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * Created by tiger on 2018/11/22.
 */
@Component
//order是用来指定初始顺序,value越小,越早加载
@Order(value = -9)
public class InitApolloConfigure implements CommandLineRunner {

    //从apollo获取配置信息
    @ApolloConfig
    private Config config;

    /**
     * commandLineRunner 目的就是在启动之后可以加载所需要的配置文件
     * */
    @Override
    public void run(String... strings) throws Exception {
        System.out.println("初始化>>>CommandLineRunner");
        //加载公共配置
        loadCommonConfig();
        //加载指定model的配置
        Set<String> configs = config.getPropertyNames();
        if(configs != null && ! configs.isEmpty()){
            configs.forEach(key -> {
                PropertiesUtils.properties.setProperty(key,config.getProperty(key,null));
            });
            //监听app.id中的key发生变化后就改变其值
            ApolloConfigurationChange.monitorApolloConfigurationChange(PropertiesUtils.properties,config);
        }
    }

    /**
     * 加载公共配置文件
     * */
    public void loadCommonConfig(){
        Config commonConfig = ConfigService.getConfig(PropertiesUtils.COMMON);
        if(commonConfig != null){
            for(String key : commonConfig.getPropertyNames()){
                PropertiesUtils.properties.setProperty(key,commonConfig.getProperty(key,null));
            }
            //监听app.id中的key发生变化后就改变其值
            ApolloConfigurationChange.monitorApolloConfigurationChange(PropertiesUtils.properties,config);
        }
    }
}

这里使用了org.springframework.boot.CommandLineRunner这个接口,它的作用就是在启动之后马上加载配置,相当于servletinit()方法,也可以用@PostConstruct注解。

2.4、ApolloConfigurationChange类

package com.cn.dl;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.model.ConfigChange;

import java.util.Properties;
import java.util.Set;

/**
 * apollo中的值发生改变,覆盖PropertiesUtils中键值
 * Created by Tiger on 2018/11/22.
 */
public class ApolloConfigurationChange {

    public static void monitorApolloConfigurationChange(Properties properties, Config config){
        config.addChangeListener(configChangeEvent -> {
            Set<String> keys = configChangeEvent.changedKeys();
            for(String key : keys){
                ConfigChange configChange = configChangeEvent.getChange(key);
                //覆盖旧值
                PropertiesUtils.properties.setProperty(key,configChange.getNewValue());
                System.out.println(configChange.getPropertyName()+" 的值改变了,原值:"+
                        configChange.getOldValue()+",新值:"+configChange.getNewValue());
            }
        });
    }
}

当apollo中配置修改时,这里就会监听到并覆盖PropertiesUtils中键值对

2.5、ApolloDemoController类:测试

package com.cn.dl;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Properties;

/**
 * Created by Tiger 2018/10/10.
 */
@RestController
@RequestMapping("/apollo")
public class ApolloDemoController {

    @GetMapping("/read_demo")
    public Properties apolloReadDemo(){
        return PropertiesUtils.properties;
    }
}

2.6、application.properties

server.port=7089

注意:我在本地搭建apollo的时候8080端口被占用了,所以这里修改了端口号

三、测试

1、在apollo添加配置

2、vm options配置

3、调接口 127.0.0.1:7089/apollo/read_demo

{
    "password": "DongLi#%qq123",
    "model": "apolloTestTiger",
    "url": "http://www.alibaba.com/",
    "username": "dongli@www123QQ"
}

4、修改url的值,然后发布,看日志和返回的结果

发布之后,立刻就监听到了变化,调接口也是返回修改之后的结果

{
    "password": "DongLi#%qq123",
    "model": "apolloTestTiger",
    "url": "http://www.baidu.com/",
    "username": "dongli@www123QQ"
}

四、总结

用了apollo,发现很方便,比把配置放在resources下不知道方便了多少倍,非常推荐使用。

猜你喜欢

转载自blog.csdn.net/qq_31289187/article/details/84346529