[英]Mapping list in Yaml to list of objects in Spring Boot
在我的 Spring Boot 應用程序中,我有包含以下內容的 application.yaml 配置文件。 我想將它作為帶有通道配置列表的 Configuration 對象注入:
available-payment-channels-list:
xyz: "123"
channelConfigurations:
-
name: "Company X"
companyBankAccount: "1000200030004000"
-
name: "Company Y"
companyBankAccount: "1000200030004000"
我想用 PaymentConfiguration 對象列表填充 @Configuration 對象:
@ConfigurationProperties(prefix = "available-payment-channels-list")
@Configuration
@RefreshScope
public class AvailableChannelsConfiguration {
private String xyz;
private List<ChannelConfiguration> channelConfigurations;
public AvailableChannelsConfiguration(String xyz, List<ChannelConfiguration> channelConfigurations) {
this.xyz = xyz;
this.channelConfigurations = channelConfigurations;
}
public AvailableChannelsConfiguration() {
}
// getters, setters
@ConfigurationProperties(prefix = "available-payment-channels-list.channelConfigurations")
@Configuration
public static class ChannelConfiguration {
private String name;
private String companyBankAccount;
public ChannelConfiguration(String name, String companyBankAccount) {
this.name = name;
this.companyBankAccount = companyBankAccount;
}
public ChannelConfiguration() {
}
// getters, setters
}
}
我將它作為帶有 @Autowired 構造函數的普通 bean 注入。 xyz 的值已正確填充,但是當 Spring 嘗試將 yaml 解析為我正在獲取的對象列表時
nested exception is java.lang.IllegalStateException:
Cannot convert value of type [java.lang.String] to required type
[io.example.AvailableChannelsConfiguration$ChannelConfiguration]
for property 'channelConfigurations[0]': no matching editors or
conversion strategy found]
任何線索這里出了什么問題?
原因一定在別的地方。 僅使用 Spring Boot 1.2.2 開箱即用,無需配置,它Just Works 。 看看這個 repo - 你能把它弄壞嗎?
https://github.com/konrad-garus/so-yaml
您確定 YAML 文件看起來與您粘貼的完全一樣嗎? 沒有多余的空格、字符、特殊字符、錯誤縮進或類似的東西? 您是否有可能在搜索路徑中的其他位置使用另一個文件而不是您期望的文件?
RefreshScope
在與@Configuration
使用時有一些問題。 請看 這個github問題像這樣改變你的班級:
@ConfigurationProperties(prefix = "available-payment-channels-list")
@Configuration
public class AvailableChannelsConfiguration {
private String xyz;
private List<ChannelConfiguration> channelConfigurations;
// getters, setters
public static class ChannelConfiguration {
private String name;
private String companyBankAccount;
// getters, setters
}
}
我已經參考了這篇文章和許多其他文章,但沒有找到一個清晰簡潔的回復來提供幫助。 我提供了我的發現,從這個線程中得到了一些參考,如下:
Spring-Boot 版本:1.3.5.RELEASE
Spring-Core 版本:4.2.6.RELEASE
依賴管理:Brixton.SR1
以下是相關的 yaml 摘錄:
tools:
toolList:
-
name: jira
matchUrl: http://someJiraUrl
-
name: bamboo
matchUrl: http://someBambooUrl
我創建了一個 Tools.class:
@Component
@ConfigurationProperties(prefix = "tools")
public class Tools{
private List<Tool> toolList = new ArrayList<>();
public Tools(){
//empty ctor
}
public List<Tool> getToolList(){
return toolList;
}
public void setToolList(List<Tool> tools){
this.toolList = tools;
}
}
我創建了一個 Tool.class:
@Component
public class Tool{
private String name;
private String matchUrl;
public Tool(){
//empty ctor
}
public String getName(){
return name;
}
public void setName(String name){
this.name= name;
}
public String getMatchUrl(){
return matchUrl;
}
public void setMatchUrl(String matchUrl){
this.matchUrl= matchUrl;
}
@Override
public String toString(){
StringBuffer sb = new StringBuffer();
String ls = System.lineSeparator();
sb.append(ls);
sb.append("name: " + name);
sb.append(ls);
sb.append("matchUrl: " + matchUrl);
sb.append(ls);
}
}
我通過@Autowired 在另一個班級中使用了這個組合
@Component
public class SomeOtherClass{
private Logger logger = LoggerFactory.getLogger(SomeOtherClass.class);
@Autowired
private Tools tools;
/* excluded non-related code */
@PostConstruct
private void init(){
List<Tool> toolList = tools.getToolList();
if(toolList.size() > 0){
for(Tool t: toolList){
logger.info(t.toString());
}
}else{
logger.info("*****----- tool size is zero -----*****");
}
}
/* excluded non-related code */
}
在我的日志中記錄了名稱和匹配的 url。 這是在另一台機器上開發的,因此我不得不重新輸入以上所有內容,所以如果我不小心打錯了,請提前原諒我。
我希望這個整合評論對很多人有幫助,我感謝這個線程的以前的貢獻者!
我也有很多問題。 我終於知道最后的交易是什么了。
參考@Gokhan Oner 的答案,一旦您獲得了代表您的對象的 Service 類和 POJO,您的 YAML 配置文件就會變得簡潔而簡潔,如果您使用注解 @ConfigurationProperties,您必須明確獲取該對象才能使用它。 喜歡 :
@ConfigurationProperties(prefix = "available-payment-channels-list")
//@Configuration <- you don't specificly need this, instead you're doing something else
public class AvailableChannelsConfiguration {
private String xyz;
//initialize arraylist
private List<ChannelConfiguration> channelConfigurations = new ArrayList<>();
public AvailableChannelsConfiguration() {
for(ChannelConfiguration current : this.getChannelConfigurations()) {
System.out.println(current.getName()); //TADAAA
}
}
public List<ChannelConfiguration> getChannelConfigurations() {
return this.channelConfigurations;
}
public static class ChannelConfiguration {
private String name;
private String companyBankAccount;
}
}
然后就到這里了。 這很簡單,但我們必須知道我們必須調用對象 getter。 我在等待初始化,希望對象是用值構建的,但沒有。 希望能幫助到你 :)
我嘗試了兩種解決方案,都有效。
解決方案_1
.yml
available-users-list:
configurations:
-
username: eXvn817zDinHun2QLQ==
password: IP2qP+BQfWKJMVeY7Q==
-
username: uwJlOl/jP6/fZLMm0w==
password: IP2qP+BQKJLIMVeY7Q==
登錄信息.java
@ConfigurationProperties(prefix = "available-users-list")
@Configuration
@Component
@Data
public class LoginInfos {
private List<LoginInfo> configurations;
@Data
public static class LoginInfo {
private String username;
private String password;
}
}
List<LoginInfos.LoginInfo> list = loginInfos.getConfigurations();
解決方案_2
.yml
available-users-list: '[{"username":"eXvn817zHBVn2QLQ==","password":"IfWKJLIMVeY7Q=="}, {"username":"uwJlOl/g9jP6/0w==","password":"IP2qWKJLIMVeY7Q=="}]'
爪哇
@Value("${available-users-listt}")
String testList;
ObjectMapper mapper = new ObjectMapper();
LoginInfos.LoginInfo[] array = mapper.readValue(testList, LoginInfos.LoginInfo[].class);
對我來說,解決方法是在用@ConfigurationProperites 注釋的類中添加注入的類作為內部類,因為我認為您需要@Component 來注入屬性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.