我有一个项目,我想配置字符串键“组” 字符串键“命令”的字符串数组。也就是说,我想 能够表达的东西像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文件已更改为“目录列表”,而其他文件则更改为列表(' - ')而不是地图。 –