自动装配清单<list <string>&gt;超出未知密钥长度的属性文件

时间:2016-02-03 09:05:30

标签: java spring autowired properties-file

有没有办法在包含从属性文件中读取的另一个列表中包含字符串的列表自动装配?我发现的困难是属性值需要拆分成一个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(由“,”拆分)? 可能这整个方法并不是最好的。如果是这样,请随时告诉我。

3 个答案:

答案 0 :(得分:2)

好吧,以下是一个非常有弹性的&#34;解决方案,虽然我认为可以解决这个问题更加优雅(根本不编写自定义代码):

写一个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&#39;调整&#39;然后将值连接到字段。通过在它们上调用splitValues方法来原始值:

@Value("#{PropertyMapper.splitValues('testProps')}")
private List<List<String>> allPaths;

答案 1 :(得分:0)

您可以使用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);
    }
}

答案 2 :(得分:0)

您可以做的是将所有作业的所有目录存储在一个值中。作业将由一个特殊字符分隔,该字符当然不会在任何目录名称中使用。

为了保持可读性,您可以use a multiline 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("|");

获取所有作业配置数组的值。

旁注:分隔符可以是reserved filename characters中的任何一个,但请务必选择目标平台上无效的分隔符。阅读维基百科文章了解更多信息。

我在示例中使用了|,这是commom操作系统在文件名中不允许的,但在Unix文件名中允许