我有一個項目,我想配置字符串鍵「組」 字符串鍵「命令」的字符串數組。也就是說,我想 能夠表達的東西像config.yml以下,並通過 消費@ConfigurationProperties(PREFIX =「config.base」):如何使用@ConfigurationProperties進行列表值或數組值映射?
---
config:
base:
"bin group":
- "Directory Listing": ["/bin/ls", "-la"]
- "Server Date/Time": ["/bin/date", "-u"]
"usr/bin group":
- "Find .txt Files": ["/usr/bin/find", ".", "-name", "*.txt"]
"usr/local/bin group":
- "Tree Listing": ["/usr/local/bin/tree"]
理想的情況下,我d想@ConfigurationProperties對象是一個LinkedHashMap<String, LinkedHashMap<String, String[]>>
但我不知道如何做到這一點。或者任何合理的接近。 我已經得到最接近的是這樣的:
package us.w7tek.bug;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import javax.annotation.PostConstruct;
import java.util.LinkedHashMap;
@EnableConfigurationProperties
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
@ConfigurationProperties("someConfig")
@Bean
public ExternalizedConfig externalizedConfig() { return new ExternalizedConfig(); }
public static class ExternalizedConfig extends LinkedHashMap<String, String[]> {
// oops, @ConfigurationProperties ends up putting LinkedHashMap<String, String> in the values of the top-level mapping,
// and that second-level LinkedHashMap has keys that could have come from Integer#toString
}
@Controller
public static class ControllerThatConsumesConfig {
private static final String A_KEY_THAT_COULDNT_BE_A_PROPERTY_NAME = "this == config cannot be expressed as a bean with properties, because the keys cannot be made into Java language identifiers for bean property setters and getters";
@Autowired
ExternalizedConfig config;
@PostConstruct
void init() {
String[] strings = config.get(A_KEY_THAT_COULDNT_BE_A_PROPERTY_NAME); // ClassCastException occurs here
// doesn't have to occur in @PostConstruct, that was just a convenient place for my demo.
}
}
}
用下面的例子application.yml
項目:
---
someConfig:
"this is a key": ["this", "value", "is", "not", "an", "String[]"]
"this is another key": ["it", "is", "deserialized", "as", "LinkedHashMap", "having", "keys", "like", "\"0\"", "and", "\"1\"", "etc."]
"this == config cannot be expressed as a bean with properties, because the keys cannot be made into Java language identifiers for bean property setters and getters": ["thereby", "subverting", "Java's", "static", "typing", "and", "resulting", "in", "ClassCastException", "at", "runtime"]
正如評論指出,該代碼爆炸當彈簧引導@ConfigurationProperties
粘結劑創建一個LinkedHashMap<String, LinkedHashMap<String, LinkedHashMap<String, String>>>
類型的對象,並將其放在config
字段中。當然,只要有任何方法根據其靜態聲明類型訪問config
,就會發生ClassCastException
。我不確定是否相信這是一個使用@ConfigurationProperties
所使用的屬性聯編程序代碼的錯誤,或者只是我的重大誤解。我認爲上面的代碼是展示問題的最簡單的事情。也可在https://github.com/w7tek/demo-configproperties-bug.git找到,以防有人想編譯並運行以查看堆棧跟蹤。
有沒有人有收集@ConfigurationProperties
的任何例子?通過簡單地將聲明的類型與Spring已經反序列化的實際類型進行匹配,我可以從中找到前進的方向,但這最終導致使用起來不方便。如果可能的話,我真的很想獲得這個配置的最內層的值,如列表<>或數組類型,但我不知道如何。
這並不能真正解決問題,但感謝您的嘗試。 運行解決方案時,傳遞給setBase的事物的實際類型與聲明的類型不同:它是同一問題的另一個示例。我認爲可以說這個問題是「Spring的屬性訪問器無法看到過去的類型擦除」。列表以「0」,「1」,「2」等鍵作爲LinkedHashMap 傳遞。換句話說,同樣的問題。 –
如果鍵包含一個點,則必須使用括號表示法,即'foo.items [two.bar] = 2'將設置'two.bar'鍵。 https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding –
這個答案產生你所要求的:'bin group = {Directory Listing = [/ bin/ls, -la],Server Date/Time = [/ bin/date,-u]},usr/bin group = {Find .txt Files = [/ usr/bin/find,。,-name,*。txt]},usr/local/bin group = {Tree Listing = [/ usr/local/bin/tree]}}'。請注意,yaml文件已更改爲「目錄列表」,而其他文件則更改爲列表(' - ')而不是地圖。 –