Как мне представить XML-файл как объект Java, используя commons-digester?
Следуя моему недавнему вопросу, касающемуся разбора XML-файлов в Java, я решил использовать библиотеку commons-digester. Теперь я знаком с этим процессом и хочу создать класс Java, представляющий файл XML, чтобы при создании экземпляра нового объекта этого класса все данные из файла XML были доступны.
Чтобы проиллюстрировать это, у меня есть файл XML с именем MyConfig.xml, имеющий следующую структуру:
<MyConfig>
<ServerName>nile</ServerName>
<ServerPort>8079</ServerPort>
</MyConfig>
У меня также есть класс Java, который называется MyConfig.java, который представляет этот файл XML. Он имеет конструктор, который принимает местоположение XML-файла, а затем анализирует и выводит содержимое XML-файла. Класс имеет следующую структуру:
package com.digestersample;
import java.io.File;
import java.io.IOException;
import org.apache.commons.digester.Digester;
import org.xml.sax.SAXException;
public class MyConfig {
private String serverName;
private String serverPort;
public MyConfig(String configFile) throws IOException, SAXException
{
Digester digester = new Digester();
digester.setValidating(false);
digester.addObjectCreate("MyConfig", MyConfig.class);
digester.addCallMethod("MyConfig/ServerName", "setServerName", 0);
digester.addCallMethod("MyConfig/ServerPort", "setServerPort", 0);
System.out.println("Creating MyConfig...");
MyConfig mc = (MyConfig) digester.parse(new File(configFile));
System.out.println("Done.");
System.out.println("Port: " + mc.getServerName());
System.out.println("Port: " + mc.getServerPort());
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public String getServerPort() {
return serverPort;
}
public void setServerPort(String serverPort) {
this.serverPort = serverPort;
}
}
Мой вопрос заключается в том, как изменить этот класс, чтобы всякий раз, когда какой-либо другой компонент создавал новый объект класса, содержимое экземпляра XML-файла было доступно в экземпляре. Например:
package com.digestersample;
import java.io.IOException;
import org.xml.sax.SAXException;
public class MyOtherClass {
public static void main(String[] args) {
MyConfig mc;
try {
mc = new MyConfig("/home/user/MyConfig.xml");
System.out.println( mc.getServerName() );
System.out.println( mc.getServerPort() );
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
}
В настоящий момент вышеуказанная реализация вызывает исключение java.lang.InstantiationException.
Благодарю.
2 ответа
Прошло много времени с тех пор, как я посмотрел на дайджестер общих ресурсов, но я ожидаю, что исключение InstantiationException связано с тем, что дайджест ожидает, что класс MyConfig будет JavaBean. Одной из определяющих характеристик JavaBean является то, что он имеет открытый конструктор с нулевым аргументом.
Вы можете подумать об использовании другого класса для создания вашего экземпляра MyConfig:
public class MyConfigFactory
public MyConfig createMyConfig(String configFile) throws IOException, SAXException
{
Digester digester = new Digester();
digester.setValidating(false);
digester.addObjectCreate("MyConfig", MyConfig.class);
digester.addCallMethod("MyConfig/ServerName", "setServerName", 0);
digester.addCallMethod("MyConfig/ServerPort", "setServerPort", 0);
MyConfig mc = (MyConfig) digester.parse(new File(configFile));
return mc;
}
}
Я понимаю, что это не прямой ответ на ваш вопрос, но это чертовски много кода для такой простой конфигурации и ваших проблем. Как упоминалось в вашем оригинальном посте, Simple XML http://simple.sourceforge.net/, на мой взгляд, делает эту работу намного лучше.
@Root
public class MyConfig {
@Element
private String serverName;
@Element
private int serverPort
public MyConfig() {
super();
}
public MyConfig(File file) {
Style style = new CamelCaseStyle();
Persister persister = new Persister(style);
persister.read(this, file);
}
public String getServerName() {
return name;
}
public int getServerPort() {
return port;
}
}
И создать это с.
MyConfig mc = new MyConfig("/home/user/MyConfig.xml");
System.out.println("Name: " + mc.getServerName());
System.out.println("Port: " + mc.getServerPort());
Готово! и вы не увидите никаких исключений. Кроме того, за исключением исключительной ситуации, вы пропускаете открытый конструктор без аргументов, аналогичный тому, который я добавил в пример MyConfig.