【问题标题】:Spring Boot - YML config - Erase entry when mergingSpring Boot - YML 配置 - 合并时擦除条目
【发布时间】:2019-04-10 20:55:31
【问题描述】:

我的应用有一个基本的 YML 配置,在类路径中如下所示:

hello-world:
  values:
    bar:
      name: bar-name
      description: bar-description
    foo:
      name: foo-name
      description: foo-description

hello-world 包含一个从字符串到 POJO 的映射,称为值。我想覆盖 hello-world 中的设置,特别是我想删除一个条目。所以在我运行应用程序的本地目录上,我有这个 application.yml:

hello-world:
  values:
    bar:
      name: bar-name
      description: bar-description

source: from-the-local-dir

但这不起作用,因为当我的本地配置覆盖现有配置时,地图会合并为一个,并保留原始条目“foo”。有没有办法在 spring yml 中从配置映射中显式删除条目?

PS:通过修改本地文件中的“bar”条目,我可以看到本地文件被拾取。这是完整的代码,我添加了一个“源”配置来告诉最后加载哪个文件:

@Import(PlayGround.Config.class)
@SpringBootApplication
public class PlayGround {

    @Autowired
    Config config;

    @Value("${source}")
    String source;

    public void start() {
        System.out.println(config);
        System.out.println(source);
    }

    public static void main(String[] args) {
        System.out.println(Arrays.toString(args));
        ConfigurableApplicationContext context = SpringApplication.run(PlayGround.class, args);
        PlayGround playGround = context.getBean(PlayGround.class);
        playGround.start();
    }

    @ConfigurationProperties(prefix = "hello-world")
    public static final class Config {
        Map<String, Information> values = new HashMap<String, Information>();

        public Map<String, Information> getValues() {
            return values;
        }

        public void setValues(Map<String, Information> values) {
            this.values = values;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this)
                    .add("values", values)
                    .toString();
        }
    }

    public static final class Information {

        String name;
        String description;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this)
                    .add("name", name)
                    .add("description", description)
                    .toString();
        }
    }

}

【问题讨论】:

    标签: java spring spring-boot configuration yaml


    【解决方案1】:

    Spring boot 默认从 src/main/resource/application.yml 获取文件 您可以声明 config/application.yml 并且这些配置将覆盖 src/main/resources 中的 application.yml

    你可以试试 src/main/resources/application.yml:

    hello-world:
      bar: 
        name: bar-name
        description: bar-description
      foo: 
        name: foo-name
        description: foo-description
    

    还有 config/application.yml

      hello-world:
          bar: 
            name: bar-name
            description: bar-description
    

    我认为这会有所帮助 因此,当您运行应用程序时,config/application.yml 将覆盖您现有的 src/main/resources/application.yml

    您可以从 config/application.yml 中完全删除 hello-world 但它会抛出类似的运行时异常:

    Could not resolve placeholder 'hello-world.foo' in value "${hello-world.foo}
    

    要修复它,您可以应用注入值,例如: @Value("${hello-world.foo:}") 在“:”之后,您可以定义默认值

    你可以在 config/application.yml 中留空

    hello-world:
      bar: 
        name: bar-name
        description: bar-description
      foo: 
        name:
        description:
    

    默认情况下,如果您不指定 foo 中的所有值,则 foo 将为空(''),然后您可以从地图中过滤和删除具有空值的条目。 你也可以看看这个类:

    https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/YamlProcessor.ResolutionMethod.html

    【讨论】:

    • 感谢您的回答。我的问题是合并过程会将两张地图合并在一起。因此,来自 src/main/resources/application.yml 的映射将使用来自 config/application.yml 的条目进行更新。如果我想更改“栏”条目的内容,它可以正常工作,但如果我想一起删除栏,它就不起作用
    • 不要在 config/application.yml 中声明 hello-world:
    • 嘿,它没有削减它。我正在尝试找到一种方法来删除设置映射中的条目。我已经编辑了我的答案以更清楚。我可以看到我可以使用本地 application.yml 覆盖我的设置,但是我无法将该设置文件设置为显式删除地图条目。类路径目录中的映射条目始终存在。
    • 好的,所以唯一的方法是将值留空并手动删除它们。关于ResolutionMethod,如何指定使用哪一种?
    • 我不知道它需要深入调查 YamlParser 的工作原理,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2018-02-21
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    相关资源
    最近更新 更多