使用Apache Commons Configuration和BeanUtils将数组从XML读入bean

时间:2015-03-09 10:45:48

标签: java apache-commons-beanutils apache-commons-config

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

<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没有。它总是只取最后一个值。

我提出了一个解决方案,它或多或少地通过滥用可以在数组中读取单个String的事实来工作。我添加了行config.setAttributeSplittingDisabled(true);。结果如下:

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

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

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

我使用的是Java 8,Configuration 1.10和BeanUtils 1.9.2。

0 个答案:

没有答案