4

在配置文件中,我有多个数组值,例如电话簿的名称。

<configuration>
    <phonebook>
        <name>John</name>
        <name>Mary</name>
    </phonebook>
</configuration>

我想通过 BeanHelper (或其他方式)将这些读入这个 bean:

public interface Phonebook {
    public void setName(String[] names);

    public String[] getName();
}

或者理想情况下使用列表java.util.List<String>而不是数组String[]。接口的实现很简单:

public class MyPhonebook implements Phonebook {
    private String[] names;
    
    @Override
    public void setName(String[] names) {
        this.names = names;
    }

    @Override
    public String[] getName() {
        return names;
    }

    @Override
    public String toString() {
        return String.join("; ", names);
    }
}

主要看起来像这样:

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationRuntimeException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.beanutils.BeanHelper;
import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;

public class Main {

    private static Phonebook myPhonebook;
    private static XMLConfiguration config;

    public static void main(String[] args) {
        // read the configuration
        String configFile = "config.xml";
        try {
            config = new XMLConfiguration();
//            config.setAttributeSplittingDisabled(true);
            config.setFileName(configFile);
            config.load();
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }

        // this is to see which keys and values are inside the configuration
        config.getKeys().forEachRemaining(
                s -> System.out.println(s + " : " + config.getProperty(s)));

        // try to create the bean
        try {
            XMLBeanDeclaration declaration = new XMLBeanDeclaration(config,
                    "phonebook");

            declaration.getBeanProperties().forEach(
                    (k, v) -> System.out.println(k + " : " + v));

            myPhonebook = (Phonebook) BeanHelper.createBean(declaration,
                    MyPhonebook.class);
        } catch (ConfigurationRuntimeException e) {
            e.printStackTrace();
        }

        // print out the bean
        System.out.println(myPhonebook);
    }
}

这在尝试创建 bean 时不起作用,我得到一个ConfigurationRuntimeException由此引起的UnsupportedOperationException

java.lang.UnsupportedOperationException: Unable to handle collection of type : [Ljava.lang.String; for property name
    at org.apache.commons.configuration.beanutils.BeanHelper.createPropertyCollection(BeanHelper.java:335)
    at org.apache.commons.configuration.beanutils.BeanHelper.initBean(BeanHelper.java:213)
    at org.apache.commons.configuration.beanutils.DefaultBeanFactory.initBeanInstance(DefaultBeanFactory.java:108)
    at org.apache.commons.configuration.beanutils.DefaultBeanFactory.createBean(DefaultBeanFactory.java:64)
    at org.apache.commons.configuration.beanutils.BeanHelper.createBean(BeanHelper.java:390)
    ... 2 more

我必须更改的第一件事是 XML 文件的布局,以匹配XMLBeanDeclarationXMLConfiguration的文档:

<configuration>
    <phonebook name="John,Mary" />
</configuration>

如果我运行该程序,它会正常终止,我的输出是:

phonebook[@name] : [John, Mary]
name : Mary
Mary

这意味着XMLConfiguration正确标识了属性名称中具有数组的配置文件,但不知何故 XMLBeanDeclaration 没有。它总是只取最后一个值。

我想出了一个解决方案,它或多或少是通过滥用可以将数组读取为单个Strings 的事实。我添加了行config.setAttributeSplittingDisabled(true);。结果如下:

phonebook[@name] : John,Mary
name : John,Mary
John; Mary

在这种情况下,似乎在创建 bean 时BeanHelper实现了数组并能够选择正确的方法。

由于这使我的配置有点不灵活,我想知道是否有可能XMLBeanDeclaration在早期阶段让 to 处理数组以避免调用config.setAttributeSplittingDisabled(true);?

我正在使用 Java 8、配置 1.10 和 BeanUtils 1.9.2。

4

0 回答 0