Environment variables for list in spring boot configuration

26 浏览
0 Comments

Environment variables for list in spring boot configuration

对于我的Spring Boot应用程序,我正在尝试使用存储在application.yml中的properties.topics列表的环境变量(参见下面的配置)。

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

我使用配置文件填充属性bean(请参见此spring文档),如下所示

import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("properties")
public class ApplicationProperties {
  private List topics = new ArrayList<>();
  public void setTopics(List topics) {
     this.topics = topics;
  }
  public List 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

admin 更改状态以发布 2023年5月20日
0
0 Comments

建议,不要过于复杂化。

比如说你想将那个列表设置为一个环境变量。你可以这样设置:

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


你可以使用注入的环境变量Bean恢复它,并创建一个新的List Bean。

@Bean
@Qualifier("topics")
List 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 topics;
   ...
}


甚至可以这样:

@Service
class TopicService {
   private final List topics;
   TopicService(@Topics final List topics) {
      this.topics = topics;
   }
   ...
}


你可以使用外部化文件。
将文件路径作为环境参数传递。

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


然后使用环境Bean获取路径。读取文件内容并请求Jackson反序列化它。
你还需要创建一个简单的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 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

0
0 Comments

可能已经晚了,但我也遇到了同样的问题,这个解决方案很好用

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

0