弹簧引导配置中列表的环境变量

2022-09-03 00:05:18

对于我的 Spring Boot 应用程序,我正在尝试使用保存 in 列表的环境变量(请参阅下面的配置)。properties.topicsapplication.yml

properties:
      topics:
        - topic-01
        - topic-02
        - topic-03

我使用配置文件来填充属性bean(请参阅此弹簧文档),如下所示

import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("properties")
public class ApplicationProperties {
  private List<String> topics = new ArrayList<>();
  public void setTopics(List<String> topics) {
     this.topics = topics;
  }
  public List<String> getTopics() {
     return this.topics;
  }
}

通过使用环境变量,我可以更改列表的内容,而无需更改 .但是,到目前为止,我能找到的所有示例仅适用于环境变量仅包含单个值的情况,而不是我的情况下的值集合。application.yml

编辑:

为了在@vancleff的评论之后明确这一点,我不需要将环境变量的值保存到。application.yml

另一个编辑:

我认为通过过度简化我的问题,我向自己开了一枪。@LppEdd答案与我的问题中给出的示例配合得很好。但是,如果我需要一个更复杂的结构,而不是一个简单的字符串主题名称的集合,会发生什么情况。例如,类似

properties:
  topics:
    - 
      name: topic-01
      id: id-1
    - 
      name: topic-02
      id: id-2
    - 
      name: topic-03
      id: id-3

答案 1

节目有点晚了,但是,我遇到了同样的问题,这解决了它

https://github.com/spring-projects/spring-boot/wiki/Relaxed-Binding-2.0#lists-1

MY_FOO_1_ = my.foo[1]

MY_FOO_1_BAR = my.foo[1].bar

MY_FOO_1_2_ = my.foo[1][2]`

因此,对于问题中的示例:

properties:
  topics:
    - 
      name: topic-01
      id: id-1
    - 
      name: topic-02
      id: id-2
    - 
      name: topic-03
      id: id-3

环境变量应如下所示:

PROPERTIES_TOPICS_0_NAME=topic-01
PROPERTIES_TOPICS_0_ID=id-01
PROPERTIES_TOPICS_1_NAME=topic-02
PROPERTIES_TOPICS_1_ID=id-02
PROPERTIES_TOPICS_2_NAME=topic-03
PROPERTIES_TOPICS_2_ID=id-03

答案 2

建议,不要过于复杂。

假设您希望该列表作为变量。您可以使用以下命令进行设置Environment

-Dtopics=topic-01,topic-02,topic-03

然后,您可以使用注入的Bean恢复它,并创建一个新的Bean。EnvironmentList<String>

@Bean
@Qualifier("topics")
List<String> topics(final Environment environment) {
    final var topics = environment.getProperty("topics", "");
    return Arrays.asList(topics.split(","));
}

从现在开始,这可以是.
您还可以考虑创建自定义限定符批注,也许是 。List@Autowired@Topics

然后

@Service
class TopicService {
   @Topics
   @Autowired
   private List<String> topics;

   ...
}

甚至

@Service
class TopicService {
   private final List<String> topics;

   TopicService(@Topics final List<String> topics) {
      this.topics = topics;
   }

   ...
}

您可以做的是使用外化文件。
将该文件的路径传递给环境参数。

-DtopicsPath=C:/whatever/path/file.json

然后使用Bean来恢复该路径。读取文件内容并要求反序列化它EnvironmentJackson

您还需要创建一个简单的类Topic

public class Topic {
    public String name;
    public String id;
}

它表示此数组的元素JSON

[
    {
        "name": "topic-1",
        "id": "id-1"
    },
    {
        "name": "topic-2",
        "id": "id-2"
    }
]

@Bean
List<Topic> topics(
        final Environment environment,
        final ObjectMapper objectMapper) throws IOException {
    // Get the file path
    final var topicsPath = environment.getProperty("topicsPath");

    if (topicsPath == null) {
        return Collections.emptyList();
    }

    // Read the file content
    final var json = Files.readString(Paths.get(topicsPath));

    // Convert the JSON to Java objects
    final var topics = objectMapper.readValue(json, Topic[].class);
    return Arrays.asList(topics);
}

enter image description here


推荐