我正在摆弄一个想法,但无法控制它。
我有一个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中编写代码,在运行时动态创建变量并通过方法公开它们而不实际编写方法吗?
这可能吗?
提前致谢,
克里斯
答案 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
是包含type
,value
和constant
的POJO领域。
您应该能够通过迭代地图来访问您的选项。无需动态创建变量。
这个blog entry已经详细介绍了如何将json转换为POJO