Environment variables for list in spring boot configuration
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
建议,不要过于复杂化。
比如说你想将那个列表设置为一个环境变量。你可以这样设置:
-Dtopics=topic-01,topic-02,topic-03
你可以使用注入的环境变量Bean恢复它,并创建一个新的List
@Bean @Qualifier("topics") Listtopics(final Environment environment) { final var topics = environment.getProperty("topics", ""); return Arrays.asList(topics.split(",")); }
自此以后,这个List可以使用@Autowired自动注入。
你还可以考虑创建自定义的限定符注释,例如@Topics。
然后:
@Service class TopicService { @Topics @Autowired private Listtopics; ... }
甚至可以这样:
@Service class TopicService { private final Listtopics; 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 Listtopics( 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); }
可能已经晚了,但我也遇到了同样的问题,这个解决方案很好用
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