[英]Autowire List<List<String>> out of properties file with unknown keys length
有没有办法自动将包含字符串的列表放在从属性文件读取的另一个列表中? 我发现的困难是属性值需要拆分成一个String列表(或数组),然后自动连接到。 我的属性文件看起来像这样:
jobFolders1=C:/Temp/originFolder, C:/Temp/trafoIn, C:/Temp/trafoOut, C:/Temp/destinationFolder
jobFolders2=C:/Temp/originFolder2, C:/Temp/trafoIn2, C:/Temp/trafoOut2, C:/Temp/destinationFolder2
现在,我希望我的用户能够在有新作业时为该文件添加行。 所以我永远不知道键的名称,也不知道行的数量。 有没有办法将文件条目自动装入List,它本身包含一个包含4个字符串的List(由“,”拆分)? 可能这整个方法并不是最好的。 如果是这样,请随时告诉我。
好吧,以下是一个相当“弹性”的解决方案,虽然我认为可以解决这个更优雅(没有编写自定义代码):
写一个PropertyMapper:
@Component("PropertyMapper")
public class PropertyMapper {
@Autowired
ApplicationContext context;
@Autowired
List<List<String>> split;
public List<List<String>> splitValues(final String beanname) {
((Properties) this.context.getBean(beanname)).values().forEach(v -> {
final List<String> paths = Arrays.asList(((String) v).split(","));
paths.forEach(p -> paths.set(paths.indexOf(p), p.trim()));
this.split.add(paths);
});
return this.split;
}
在context.xml中加载属性,如下所示:
<util:properties id="testProps" location="classpath:test.properties"/>
然后将值连接到字段,使用Spring EL'通过调用splitValues方法'调整'原始值:
@Value("#{PropertyMapper.splitValues('testProps')}")
private List<List<String>> allPaths;
您可以使用Apache Commons Configuration 。 getKeys()方法将为您提供配置中包含的键列表。 刷新策略确保您能够动态加载在运行时添加的新属性。 为方便起见,我编写了一个示例,但尚未对其进行测试。
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.log4j.Logger;
public class SystemProperties {
private static final Logger LOG = Logger.getLogger(SystemProperties.class.getSimpleName());;
private static SystemProperties singleton = new SystemProperties();
private PropertiesConfiguration conf = null;
private final FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy();
private static final long REFRESH_INTERVAL = 2000;
private final String configurationFilePath = "/my-properties-files/system.properties";
private SystemProperties()
{
conf = new PropertiesConfiguration();
conf.setDelimiterParsingDisabled(true);
if (conf.getFile() == null)
{
try {
URL url = getClass().getResource(configurationFilePath);
File configurationFile = new File(url.getFile());
InputStream in = new FileInputStream(url.getFile());
conf.load(in);
conf.setFile(configurationFile);
} catch (final Exception ex) {
LOG.error("SystemProperties: Could not load properties file ", ex);
}
}
if (conf.getFile() == null)
{
LOG.warn("File could not be loaded");
}
strategy.setRefreshDelay(REFRESH_INTERVAL);
conf.setReloadingStrategy(strategy);
conf.setAutoSave(true);
}
public static SystemProperties getInstance()
{
return singleton;
}
public String get(String s)
{
return conf.getString(s);
}
public List<String> getKeys()
{
@SuppressWarnings("unchecked")
final Iterator<String> keysIterator = conf.getKeys();
if (keysIterator != null) {
final List<String> keysList = new ArrayList<String>();
while(keysIterator.hasNext()) {
keysList.add(keysIterator.next());
}
return keysList;
}
return Collections.emptyList();
}
public void setProperty(String property, String value) throws Exception
{
conf.setProperty(property, value);
}
}
您可以做的是将所有作业的所有目录存储在单个值中。 作业将由一个特殊字符分隔,该字符当然不会在任何目录名称中使用。
为了使其可读,您可以使用多行属性值 。 例如,使用|
(管道)作为分隔符:
# Starting with a line break for readability.
# Looks nice, but the first array value will be empty.
# Just leave it out if you don't want this.
jobFolders=|\
C:/Temp/originFolder, C:/Temp/trafoIn, C:/Temp/trafoOut, C:/Temp/destinationFolder|\
C:/Temp/originFolder2, C:/Temp/trafoIn2, C:/Temp/trafoOut2, C:/Temp/destinationFolder2
在您的代码中,您可以简单地申请
String[] jobs = jobFolders.split("|");
获取所有作业配置数组的值。
附注:分隔符可以是任何保留的文件名字符 ,但请确保选择在目标平台上无效的分隔符。 阅读Wikipedia文章了解更多信息。
我用过|
在示例中,commom操作系统不允许在文件名中,但可以在Unix文件名中允许。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.