Как мне представить XML-файл как объект Java, используя commons-digester? - PullRequest
0 голосов
/ 14 января 2009

Исходя из моего недавнего вопроса Что касается анализа файлов 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 ]

1 голос
/ 14 января 2009

Я понимаю, что это не прямой ответ на ваш вопрос, но это чертовски много кода для такой простой конфигурации и ваших проблем. Как упоминалось в вашем первоначальном посте, 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.

0 голосов
/ 14 января 2009

Прошло много времени с тех пор, как я посмотрел на дайджестер общих ресурсов, но я ожидаю, что 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;
    }

}
...