Java中的动态属性来自xml

时间:2014-10-28 06:08:03

标签: java xml

我正在摆弄一个想法,但无法控制它。

我有一个xml文件,其中包含100多个属性,用于定义某个大型程序的运行时环境。它们通过类暴露为变量。目前,对于xml文件中的每个选项,类中都有一个变量加上public getter和private setter。

每次我们需要一个新选项时,我们必须在xml文件中定义它并在RuntimenEnvironment类中创建变量plus方法。

现在,我想做的是这样的:我想以这样的方式重写类,它将xml文件中的新选项作为变量公开,而不必触及类。

我的xml文件使用以下结构:

<option>
  <name>theName</name>
  <type>eg int</type>
  <value>20</value>
  <constant>THE_NAME</constant>
</option>

我可以在java中编写代码,在运行时动态创建变量并通过方法公开它们而不实际编写方法吗?

这可能吗?

提前致谢,

克里斯

2 个答案:

答案 0 :(得分:1)

我能想到的几个选项是:

  • 如果名称是唯一的,则可以使用name作为键来填充地图。

  • 如果您只对选项感兴趣,那么可以选择一个选项列表 从XML填充。

以下是使用SAX解析器实现的示例代码

处理程序类

public class OptionsParser extends DefaultHandler {
    private final StringBuilder valueBuffer = new StringBuilder();
    private final Map<String, Option> resultAsMap = new HashMap<String, Option>();
    private final List<Option> options = new ArrayList<Option>();

    //variable to store the values from xml temporarily
    private Option temp;

    public List<Option> getOptions() {
        return options;
    }

    public Map<String, Option> getResultAsMap() {
        return resultAsMap;
    }

    @Override
    public void startElement(final String uri, final String localName, final String qName,
            final Attributes attributes) throws SAXException {
        if("option".equalsIgnoreCase(qName)) {
            temp = new Option();
        }
    }

    @Override
    public void endElement(final String uri, final String localName, final String qName)
            throws SAXException {
        //read the value into a string to set them to option object
        final String value = valueBuffer.toString().trim();
        switch (qName) {
        case "name":
            temp.setName(value);
            // set the value into map and name of the option is the key
            resultAsMap.put(value, temp);
            break;
        case "type":
            temp.setType(value);
            break;
        case "value":
            temp.setValue(value);
            break;
        case "constant":
            temp.setConstant(value);
            break;
        case "option":
            // this is the end of option tag add it to the list
            options.add(temp);
            temp = null;
            break;
        default:
            break;
        }
        //reset the buffer after every iteration
        valueBuffer.setLength(0);
    }

    @Override
    public void characters(final char[] ch, final int start, final int length)
            throws SAXException {
        //read the value into a buffer
        valueBuffer.append(ch, start, length);
    }
}

选项POJO

public class Option {

    private String name;
    private String type;
    private String value;
    private String constant;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public String getConstant() {
        return constant;
    }

    public void setConstant(String constant) {
        this.constant = constant;
    }
}

输入XML

<options>
    <option>
        <name>option1</name>
        <type>int</type>
        <value>20</value>
        <constant>const1</constant>
    </option>
    <option>
        <name>option2</name>
        <type>string</type>
        <value>testValue</value>
        <constant>const2</constant>
    </option>
</options>

样本主类

public class ParseXML {
        public static void main(String[] args) {
            final OptionsParser handler = new OptionsParser();
            try {
                SAXParserFactory.newInstance().newSAXParser()
                        .parse("C:/luna/sample/inputs/options.xml", handler);
            } catch (SAXException | IOException | ParserConfigurationException e) {
                System.err.println("Somethig went wrong while parsing the input file the exception is -- " + e.getMessage() + " -- ");
            }
            Map<String, Option> result = handler.getResultAsMap();
            Collection<Option> values = result.values();
            for (Option option : values) {
                System.out.println(option.getName());
            }

        }
    }

答案 1 :(得分:0)

我将讨论json配置文件。但XML也应该是类似的。 Jackson提供了反序列化JSON和创建动态对象的方法。 如果选项(theName)的名称是唯一的,则可以创建动态bean。您的xml将如下所示:

<theName>
  <type>eg int</type>
  <value>20</value>
  <constant>THE_NAME</constant>
</theName>

看,我说的是json,所以它实际上是:

theName: {
      type: "int"
      value: 20
      constant: "THE_NAME" }

动态bean包含地图,因此您的选项将存储在Map<String, Option>中,其中Option是包含typevalueconstant的POJO领域。 您应该能够通过迭代地图来访问您的选项。无需动态创建变量。 这个blog entry已经详细介绍了如何将json转换为POJO