在运行时将列表元素添加到 Spring 属性

Add list element to Spring properties at runtime

我有一个 application.yml 文件,其中包含以下内容:

topics:
  input:
    - name: topic1
      partitions: 3
      replicas: 1
    - name: topic2
      partitions: 6
      replicas: 2

我希望能够在运行时更新或添加新的主题对象。

我尝试了以下更新现有对象的方法:

java -jar app.jar --topics.input[0].name="topicX"

以及用于将另一个对象添加到列表的以下内容:

java -jar app.jar --topics.input[2].name="topicX" --topics.input[2].partitions=6 --topics.input[2].replicas=2

我通过以下方式访问属性:

@Component
@ConfigurationProperties(prefix = "topics")
@Validated
public class TopicsConfiguration {

  @NotEmpty
  @NotNull
  private List<TopicConfiguration> input = new ArrayList<>();

  public List<TopicConfiguration> getInputTopics() {
    return input;
  }

  public void setFacts(List<TopicConfiguration> input) {
    this.input = input;
  }

}

其中 TopicConfiguration 只是一个列出了 3 个字段的 POJO。

当我不尝试在运行时修改任何 属性 对象时,这完全符合我的预期,但是我根本无法更新 属性 列表。当我尝试更新现有对象时,我得到了一个 NPE。当我尝试向列表中添加一个新对象时,我得到:

Property: topics.input[2].name
    Value: lmnop
    Origin: "topics.input[2].name" from property source "commandLineArgs"
    Reason: The elements [topics.input[2].name,topics.input[2].partitions,topics.input[2].replicas] were left unbound.

我只想知道是否有任何方法可以在运行时更新或添加一个元素到列表中,这样我的项目的用户就不必修改 application.yml 如果他们想更新这个配置。

所以您想在 Spring 启动应用程序中即时重新加载 application.propertiesapplication.yml,而不必将另一个代码提交到另一个部署?如果我明白这一点,那么你可以这样做。

阅读这些链接以及 google Spring Boot Actuator Reload PropertiesSpring Scheduling 上的更多内容。我们无法为您提供 out-written 代码来实现此功能,但有大量示例可供检查和试用。

链接:

  1. Actuator Refresh
  2. Spring Scheduling

如果我是你,我更喜欢 Actuator 方法,因为它可以避免混淆并且更简洁。

好吧,所以我做了一些研究和测试,得出以下结论:

您无法更新 application.yml

中定义的列表

如果你运行:

java -jar myApp.jar -my-list[2].name=foo

它会失败,因为一旦你想传递列表,列表就会覆盖 application.yml 中的当前列表,而你正试图传递列表中的第 3 项,而此时什么也没有索引 0 和 1。

它不是一个动态列表,它是一个数组。

您需要传递整个列表:

java -jar myApp.jar -my-list[0].name=foo -my-list[1].name=bar -my-list[2].name=foobar 

因此,如果您要从 cmd 传递列表,则必须始终从头开始定义列表。