前言:实际项目开发中,经常得通过修改配置来改变业务线或者调试,对于修改代码重新打包部署,真心麻烦,所以这里找到一种不重启服务,直接修改配置文件内容,就可以生效的方式。
正文
1.话不多说,上依赖,该依赖是针对yml配置文件的操作,不要使用properties
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>
2.上配置文件,分为总的和分支
application.yml
server:
port: 9888
spring:
profiles:
active: tst
application-tst.yml
##配置变量
myTestConf: world
myTestConf2: hello
3.增加一个配置文件工具类YmlUtil.java
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 动态操作yml配置文件工具类
* 【需要将config配置文件夹和项目jar包放在同级别目录下,这样修改config下的配置文件后,jvm才能及时得获取新的配置】
*/
public class YmlUtil {
public static LinkedHashMap loadYaml(String fileName)throws Exception{
String path=System.getProperty("user.dir");
File file=new File(path+"/config/"+fileName);
InputStream in = null;
System.out.println("The config file "+path+"/config/"+fileName+" is exist? "+file.exists());
if (file.exists()) {
in = new FileInputStream(path+"/config/" + fileName);
} else {
//如果没有config文件夹,则从项目的resources目录下找
in = YmlUtil.class.getClassLoader().getResourceAsStream(fileName);
}
LinkedHashMap lhm= new Yaml().loadAs(in, LinkedHashMap.class);
return lhm;
}
public static Object getValByKey(Map lhm,String key)throws Exception{
String[] keys = key.split("[.]");
Map ymlInfo = lhm;
for (int i = 0; i < keys.length; i++) {
Object value = ymlInfo.get(keys[i]);
if (i < keys.length - 1) {
ymlInfo = (Map) value;
} else if (value == null) {
throw new Exception("key不存在");
} else {
return value;
}
}
throw new RuntimeException("不可能到这里的...");
}
}
4.增加一个配置实体类ConfValEntity.java
/**
* 配置文件实体类,供内存中使用(类中变量都是配置变量)
*/
public class ConfValEntity {
public static String myTestConf;
public static String myTestConf2;
}
5.增加一个自启动类Initialization.java,进行配置内容的定时更新
import com.wong.gogo.common.YmlUtil;
import com.wong.gogo.model.ConfValEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* spring容器初始化完成后进行一些其他初始化操作
*/
@Slf4j
@Component
public class Initialization implements ApplicationRunner {
private static ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
private static String profile;
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
scheduleUpdateConf();
}
private void scheduleUpdateConf() {
try {
Map lhm = YmlUtil.loadYaml("application.yml");
profile = (String) YmlUtil.getValByKey(lhm, "spring.profiles.active");
} catch (Exception e) {
log.error("加载配置文件application.yml异常");
}
//开启定时刷新内存中配置文件内容
log.info("refresh config file start");
exec.scheduleAtFixedRate(Initialization::updateConfVal, 0, 10, TimeUnit.SECONDS);
log.info("refresh config file end");
}
/**
* 更新配置文件值
*/
private static void updateConfVal(){
try{
Map lhm= YmlUtil.loadYaml("application-"+profile+".yml");
log.info("profile="+"application-"+profile+".yml");
String myTestConf = (String) YmlUtil.getValByKey(lhm,"myTestConf");
ConfValEntity.myTestConf = myTestConf;
String myTestConf2 = (String) YmlUtil.getValByKey(lhm,"myTestConf2");
ConfValEntity.myTestConf2 = myTestConf2;
log.info("实时配置myTestConf=="+myTestConf+",myTestConf2=="+myTestConf2);
} catch (Exception e){
log.error("更新配置文件值异常: ", e);
}
}
}
6.最后打成jar包,在jar包的同级目录下新建config文件夹,然后将配置文件放入config文件夹,完成!
7.启动jar包服务,运行期间如果修改配置文件内容,则内存中的变量值就会相应的改变。