概述
java项目启动时对yml文件的修改
- JYaml 方式
- 启动前修改yaml 的class 文件(也是我用的方式)
- 首先来一个工具类先(获取以及修改yaml文件的工具类)
- 常量文件
- 在springBoot 项目启动前先执行方法
- 私有方法(用于修改yml文件)
- 对yml文件的修改
- ContextUtil工具类
- 简单调用
JYaml 方式
这种方式我简单用了一下就放弃了,主要是他会直接修改yaml 文件内容,不是修改class 文件
下面有修改class 文件的方式
附上yml文件的读取:https://www.cnblogs.com/mysgk/p/9790801.html
参考:https://blog.csdn.net/m0_37739193/article/details/78690680
jyaml 方式代码
注意:
1、接收文件实际用时最好不要使用map,至于问什么(你用了就知道了)!
2、特别注意这种方式是直接修改的yaml文件内容,不是class 文件,改了就真是改了,提前备份下。
pom加一下
<dependency>
<groupId>org.jyaml</groupId>
<artifactId>jyaml</artifactId>
<version>1.3</version>
</dependency>
/**
* 获取文件内容
*/
//获取项目名称
String path = System.getProperty("user.dir");
//要读取的文件路径
File dumpFile = new File(path + "/qiun-service/bbjh-value-added/src/main/resources/bootstrap.yml");
//将读取的yaml转换成map
HashMap hashMap = Yaml.loadType(dumpFile, HashMap.class);
/**
* 修改文件
*/
//流读取要修改的yaml 文件
YamlEncoder enc = new YamlEncoder(new FileOutputStream(dumpFile));
//将内容写入读取的yaml文件中
enc.writeObject(hashMap);
enc.flush();
enc.close();
启动前修改yaml 的class 文件(也是我用的方式)
如果只是单纯的需要修改yml 文件,光看那个工具类就可以了
场景:需要在项目启动时修改yaml 文件中配置,项目使用修改的参数启动。
首先看一下yml 文件
spring:
profiles:
active: dev
application:
name: bbjh-value-added #nacos配置中心的 Data_Id (xxlJob.yaml)
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml #指定配置文件类型为yaml文件
group: SMS_GROUP
首先来一个工具类先(获取以及修改yaml文件的工具类)
网上找的工具类很好用
@Slf4j
@Component
public class YamlUtils {
private final static DumperOptions OPTIONS = new DumperOptions();
static {
//设置yaml读取方式为块读取
OPTIONS.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
OPTIONS.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
OPTIONS.setPrettyFlow(false);
}
/**
* 将yaml配置文件转化成map
* fileName 默认是resources目录下的yaml文件, 如果yaml文件在resources子目录下,需要加上子目录 比如:conf/config.yaml
*
* @param fileName
* @return
*/
public Map<String, Object> getYamlToMap(String fileName) {
LinkedHashMap<String, Object> yamls = new LinkedHashMap<String, Object>();
Yaml yaml = new Yaml();
try {
@Cleanup InputStream in = YamlUtils.class.getClassLoader().getResourceAsStream(fileName);
yamls = yaml.loadAs(in, LinkedHashMap.class);
} catch (Exception e) {
log.error("{} load failed !!!", fileName);
}
return yamls;
}
/**
* key格式:aaa.bbb.ccc
* 通过properties的方式获取yaml中的属性值
*
* @param key
* @param yamlMap
* @return
*/
public Object getValue(String key, Map<String, Object> yamlMap) {
String[] keys = key.split("[.]");
Object o = yamlMap.get(keys[0]);
if (key.contains(".")) {
if (o instanceof Map) {
return getValue(key.substring(key.indexOf(".") + 1), (Map<String, Object>) o);
} else {
return null;
}
} else {
return o;
}
}
/**
* 使用递归的方式设置map中的值,仅适合单一属性
* key的格式: "server.port"
* server.port=111
**/
public Map<String, Object> setValue(String key, Object value) {
Map<String, Object> result = new LinkedHashMap<String, Object>();
String[] keys = key.split("[.]");
int i = keys.length - 1;
result.put(keys[i], value);
if (i > 0) {
return setValue(key.substring(0, key.lastIndexOf(".")), result);
}
return result;
}
public Map<String, Object> setValue(Map<String, Object> map, String key, Object value) {
String[] keys = key.split("\.");
int len = keys.length;
Map temp = map;
for (int i = 0; i < len - 1; i++) {
if (temp.containsKey(keys[i])) {
temp = (Map) temp.get(keys[i]);
} else {
return null;
}
if (i == len - 2) {
temp.put(keys[i + 1], value);
}
}
for (int j = 0; j < len - 1; j++) {
if (j == len - 1) {
map.put(keys[j], temp);
}
}
return map;
}
/**
* 修改yaml中属性的值
*
* @param key key是properties的方式: aaa.bbb.ccc (key不存在不修改)
* @param value 新的属性值 (新属性值和旧属性值一样,不修改)
* @param yamlName
* @return true 修改成功,false 修改失败。
*/
public boolean updateYaml(String key, Object value, String yamlName) {
Map<String, Object> yamlToMap = this.getYamlToMap(yamlName);
if (null == yamlToMap) {
return false;
}
Object oldVal = this.getValue(key, yamlToMap);
//未找到key 不修改
if (null == oldVal) {
log.error("{} key is not found", key);
return false;
}
//不是最小节点值,不修改
if (oldVal instanceof Map) {
log.error("input key is not last node {}", key);
return false;
}
//新旧值一样 不修改
if (value.equals(oldVal)) {
log.info("newVal equals oldVal, newVal: {} , oldVal: {}", value, oldVal);
return false;
}
Yaml yaml = new Yaml(OPTIONS);
String path = this.getClass().getClassLoader().getResource(yamlName).getPath();
try {
Map<String, Object> resultMap = this.setValue(yamlToMap, key, value);
if (resultMap != null) {
yaml.dump(this.setValue(yamlToMap, key, value), new FileWriter(path));
return true;
} else {
return false;
}
} catch (Exception e) {
log.error("yaml file update failed !");
log.error("msg : {} ", e.getMessage());
log.error("cause : {} ", e.getCause());
}
return false;
}
/**
* 修改yaml中属性的值(就算key为 null也肯定会修改)
*
* @param key key是properties的方式: aaa.bbb.ccc (key不存在不修改)
* @param value 新的属性值 (新属性值和旧属性值一样,不修改)
* @param yamlName
* @return true 修改成功,false 修改失败。
*/
public boolean updateYamlToNULL(String key, Object value, String yamlName) {
Map<String, Object> yamlToMap = this.getYamlToMap(yamlName);
if (null == yamlToMap) {
return false;
}
Object oldVal = this.getValue(key, yamlToMap);
//不是最小节点值,不修改
if (oldVal instanceof Map) {
log.error("input key is not last node {}", key);
return false;
}
Yaml yaml = new Yaml(OPTIONS);
String path = this.getClass().getClassLoader().getResource(yamlName).getPath();
try {
Map<String, Object> resultMap = this.setValue(yamlToMap, key, value);
if (resultMap != null) {
yaml.dump(this.setValue(yamlToMap, key, value), new FileWriter(path));
return true;
} else {
return false;
}
} catch (Exception e) {
log.error("yaml file update failed !");
log.error("msg : {} ", e.getMessage());
log.error("cause : {} ", e.getCause());
}
return false;
}
public static void main(String[] args) {
YamlUtils configs = new YamlUtils();
Map<String, Object> yamlToMap = configs.getYamlToMap("conf/config.yaml");
System.out.println(yamlToMap);
boolean b = configs.updateYaml("sys.cpu.name", "Intel Core i7", "conf/config.yaml");
System.out.println(b);
System.out.println(configs.getYamlToMap("conf/config.yaml"));
}
}
常量文件
public interface AuthConstant {
/**
* 环境变量dev
*/
String DEV = "dev";
/**
* 环境变量prod
*/
String PROD = "prod";
/**
* 环境变量test
*/
String TEST = "test";
/**
* nacos 的dev 配置
*/
String NACOS_DEV = "127.0.0.1:8848";
/**
* nacos prod 地址
*/
String NACOS_PROD = "127.0.0.1:8849";
/**
* nacos test 地址
*/
String NACOS_TEST = "127.0.0.1:8844";
}
在springBoot 项目启动前先执行方法
该方法用于在项目启动前重置你上次修改的内容。
由于我配置的naocs 修改后,每次启动都会先执行我修改的nacos ,在执行修改方法,造成启动读取出错后中断情况。
//读取的文件
public static final String BOOTSTRAP_YML_URL = "bootstrap.yml";
/**
* nacos 地址
*/
public static final String NACOS_SERVER_ADDR = "spring.cloud.nacos.config.server-addr";
/**
* 项目启动的环境
*/
public static final String ACTIVE_CONFIG = "spring.profiles.active";
/**
* 修改nacos 默认
* 项目初始化前先执行当前参数用于初始化class 文件中的配置
*/
public void upNacosData(){
YamlUtils configs = new YamlUtils();
Map<String, Object> yamlToMap = configs.getYamlToMap(BOOTSTRAP_YML_URL);
//项目启动环境参数
Object env = configs.getValue(ACTIVE_CONFIG, yamlToMap);
//nacos 地址参数
Object nacos = configs.getValue(NACOS_SERVER_ADDR, yamlToMap);
/**
* 判断nacos 是否有值,没有则使用
*/
Object bootstrapNacos = configs.getValue(NACOS_SERVER_ADDR, yamlToMap);
if (null == bootstrapNacos || "".equals(bootstrapNacos)){
//参数默认读取dev
nacos = AuthConstant.NACOS_DEV;
env = AuthConstant.DEV;
}
//调用私有方法设置yaml 文件参数
setNacosUrl(configs, NACOS_SERVER_ADDR, nacos !=null?nacos.toString():null, BOOTSTRAP_YML_URL, ACTIVE_CONFIG, env != null ? env.toString() : null);
}
私有方法(用于修改yml文件)
/**
* 设置nacos 地址
* @param configs
* @param nacos nacos项配置位置
* @param nacosUrl nacosUrl nacos路径
* @param bootstrapYml bootstrap 文件名称
* @param activeConfig 项目启动的环境配置位置
* @param env 环境变量
*/
private void setNacosUrl(YamlUtils configs, String nacos, String nacosUrl, String bootstrapYml, String activeConfig, String env) {
//修改nacos
boolean flag = configs.updateYamlToNULL(nacos, nacosUrl, bootstrapYml);
//修改启动配置
configs.updateYamlToNULL(activeConfig, env, bootstrapYml);
log.info("环境变量:" + env + "--------------->nacos地址:" + nacosUrl);
}
对yml文件的修改
方法中用到了 String activeProfile = new ContextUtil().getActiveProfile(); 这个工具类。
当前工具类实现ApplicationContextAware方法注入bean
下面的工具类注意别落下
public void nacosDate() throws IOException {
//springBoot 启动时将环境参数放入了ApplicationContext 中,这个工具类就是获取ApplicationContext的环境参数
String activeProfile = new ContextUtil().getActiveProfile();
YamlUtils configs = new YamlUtils();
Map<String, Object> yamlToMap = configs.getYamlToMap(BOOTSTRAP_YML_URL);
System.out.println(yamlToMap);
/**
* 设置nacos 地址
*/
if (AuthConstant.TEST.equals(activeProfile)) {
setNacosUrl(configs, NACOS_SERVER_ADDR, AuthConstant.NACOS_TEST, BOOTSTRAP_YML_URL, ACTIVE_CONFIG, AuthConstant.TEST);
} else if (AuthConstant.PROD.equals(activeProfile)) {
setNacosUrl(configs, NACOS_SERVER_ADDR, AuthConstant.NACOS_PROD, BOOTSTRAP_YML_URL, ACTIVE_CONFIG, AuthConstant.PROD);
} else {
setNacosUrl(configs, NACOS_SERVER_ADDR, AuthConstant.NACOS_DEV, BOOTSTRAP_YML_URL, ACTIVE_CONFIG, AuthConstant.DEV);
}
Map<String, Object> yamlToMaprrrr = configs.getYamlToMap(BOOTSTRAP_YML_URL);
System.out.println("更改后的nacos: " + yamlToMaprrrr.toString());
}
ContextUtil工具类
使用@Component将类交由spring,非Boot 项目自己使用xml去注入
注意:在多模块项目中,这个工具类不要放到非启动的模块下比如common、core 之类的不需要启动的模块
@Component
public class ContextUtil implements ApplicationContextAware {
private static ApplicationContext context;
/* (non Javadoc)
* @Title: setApplicationContext
* @Description: spring获取bean工具类
* @param applicationContext
* @throws BeansException
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("初始化了-----------------applicationContext");
this.context = applicationContext;
}
// 传入线程中
public static <T> T getBean(String beanName) {
return (T) context.getBean(beanName);
}
// 国际化使用
public static String getMessage(String key) {
return context.getMessage(key, null, Locale.getDefault());
}
/// 获取当前环境
public String getActiveProfile() {
return context.getEnvironment().getActiveProfiles()[0];
}
简单调用
这里有时间可以自己将启动类修集成一下,将动态修改yml 集成进去
@SpringBootApplication
public class ValueAddedApplication {
public static void main(String[] args) throws IOException {
new NacosConfig().upNacosData();
SpringApplication.run(ValueAddedApplication.class,args);
new NacosConfig().nacosDate();
}
}
有没有其他好方法么,欢迎交流。
最后
以上就是机灵方盒为你收集整理的项目启动时对yml文件的修改(nacos启动地址切换样例)JYaml 方式启动前修改yaml 的class 文件(也是我用的方式)的全部内容,希望文章能够帮你解决项目启动时对yml文件的修改(nacos启动地址切换样例)JYaml 方式启动前修改yaml 的class 文件(也是我用的方式)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复