java springboot本地调试动态修改nacos配置信息

一、需求

我本地项目想直接连接测试环境nacos,由于nacos中的配置信息我不能修改,否则测试环境会出问题。但是我还想改配置怎么办呢?

可以在本地springboot项目启动拿到nacos配置时修改。

二、举个例子

例如:测试环境nacos中配置的server.tomcat.basedir配置(tomcat临时目录),在我本地无法创建相应的文件夹,导致无法启动项目,所以我就只能修改server.tomcat.basedir的值(还不能修改nacos云配置)。

无法创建对应目录,如图:

 项目启动报错,如图:

 

三、解决办法

第一种方法,借助idea的断点调试功能进行修改

1、我们找到NacosPropertySourceBuilder类的loadNacosData方法,把断点打到如图位置

 2、使用Evaluate执行dataMap.put()方法把值重新覆盖就可以了。

 以上操作,只适合临时启动用,每次启动都要修改一下,很麻烦。可以使用第二种方法。

第二种方法,使用代码修改

1、先自定义一个类实现SpringApplicationRunListener接口。

SpringApplicationRunListener是springboot的生命周期,不懂可以参考:springboot扩展点_现实、太残忍的博客-CSDN博客_springboot扩展点


@Slf4j
public class LocalHostSpringApplicationRunListener implements SpringApplicationRunListener {

    /**
     * 必须添加参数为SpringApplication application和String[] args构造方法,否则启动报错
     * @param application
     * @param args
     */
    public LocalHostSpringApplicationRunListener(SpringApplication application, String[] args) {
    }

    @Override
    public void starting() {
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
    }

    /**
     * 环境上下文准备完成时
     * @param context the application context
     */
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        //判断上下文环境是ServletWebServer环境
        if(context instanceof AnnotationConfigServletWebServerApplicationContext){
            //从上下文环境中获取总配置信息
            MutablePropertySources mutablePropertySources = context.getEnvironment().getPropertySources();
            //获取nacos配置信息
            CompositePropertySource bootstrapPropertiesCompositePropertySource = (CompositePropertySource)mutablePropertySources.get("bootstrapProperties");
            //获取nacos配置信息中的配置信息(包装了好几层)
            for (PropertySource compositePropertySource : bootstrapPropertiesCompositePropertySource.getPropertySources()) {
                for (PropertySource nacosPropertySource : ((CompositePropertySource) compositePropertySource).getPropertySources()) {
                    //最终拿到对应的配置文件信息
                    NacosPropertySource nacosPropertySourceTarget = (NacosPropertySource) nacosPropertySource;
                    //找到你要修改的文件名称(dataId)
                    if("sys-test.properties".equals(nacosPropertySourceTarget.getDataId())){
                        //修改值
                        Map<String, Object> source = nacosPropertySourceTarget.getSource();
                        source.put("server.tomcat.basedir","/tmp");
                        log.info("已修改server.tomcat.basedir为/tmp");
                    }
                };
            };
        }
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
    }

    @Override
    public void started(ConfigurableApplicationContext context) {

    }

    @Override
    public void running(ConfigurableApplicationContext context) {

    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {

    }
}

2、在resources文件夹下的META-INF文件夹创建一个spring.factories文件

解释:Spring factories是 Spring Boot 一种解耦的扩展机制,仿照了 Java 中 SPI 的扩展机制,可以实现自动加载可扫描包之外的 Bean。

 

 3、完毕

方法二具体原理:

1、通过断点可以得知,nacos获取配置阶段发生在springboot生命周期的“上下文准备阶段”。
所以是spingboot的prepareContext方法,具体发生在执行applyInitializers方法中。

其中包括一个PropertySourceBootstrapConfiguration类是springcloud的用于远程配置处理的类。

从代码中我们可以看到listeners.contextPrepared(context);,所以我们正好可以利用springboot生命周期的“上下文准备阶段”进行nacos配置的修改。

2、进行SpringApplicationRunListener的springboot生命周期接口实现

ConfigurableApplicationContext是应用的上下文信息,里面包含Environment环境信息。

Environment环境信息里面包含PropertySources配置信息。

因为配置信息有多个(本地配置,nacos配置等),所以我们要找到nacos的配置信息,一层一层获取到map然后修改

猜你喜欢

转载自blog.csdn.net/sumengnan/article/details/127051123