对于我的Spring Boot应用程序,我试图使用保存properties.topicsin 列表的环境变量application.yml(请参见下面的配置)。
properties.topics
application.yml
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<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。
另一个编辑:
I think by oversimplifying my question, I shoot myself in the foot. @LppEdd answer works well with the example given in my question. However, what happens if instead of a collection of simple string topic names, I need a bit more complex structure. For example, something like
properties: topics: - name: topic-01 id: id-1 - name: topic-02 id: id-2 - name: topic-03 id: id-3
Suggestion, don’t overcomplicate.
Say you want that list as an Environment variable. You’d set it using
Environment
-Dtopics=topic-01,topic-02,topic-03
You then can recover it using the injected Environment Bean, and create a new List<String> Bean
List<String>
@Bean @Qualifier("topics") List<String> topics(final Environment environment) { final var topics = environment.getProperty("topics", ""); return Arrays.asList(topics.split(",")); }
From now on, that List can be @Autowired. You can also consider creating your custom qualifier annotation, maybe @Topics.
List
@Autowired
@Topics
Then
@Service class TopicService { @Topics @Autowired private List<String> topics; ... }
Or even
@Service class TopicService { private final List<String> topics; TopicService(@Topics final List<String> topics) { this.topics = topics; } ... }
What you could do is use an externalized file. Pass to the environment parameters the path to that file.
-DtopicsPath=C:/whatever/path/file.json
Than use the Environment Bean to recover that path. Read the file content and ask Jackson to deserialize it
Jackson
You’d also need to create a simple Topic class
Topic
public class Topic { public String name; public String id; }
Which represents an element of this JSON array
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); }