一、从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 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这个接口,它的作用就是在启动之后马上加载配置,相当于servlet中init()方法,也可以用@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 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下不知道方便了多少倍,非常推荐使用。