簡體   English   中英

JAXB / xjc:從子元素生成類並根據類類型加載它們

[英]JAXB/xjc: Generate classes from child elements and load them based on class types

我有一個XML配置文件,看起來像:

<configuration>
     <database>
          <host></host>
          <port></port>
     </database>
     <queue>
           <host></host>
           <port></port>
           <type></type>
      </queue>
</configuration>

我想使用JAXB / xjc來為此配置生成Java類,但是我想生成這些類並將這些級別解組到樹中。 我不想接收Configuration.java,而是想要一個Database.java和Queue.java(以便可以將它們分別注入到Guice管理的應用程序中)。 我(目前)沒有任何方法可以執行此操作,但是可能正在搜索錯誤的內容。


經過一些試驗,我找到了一種生成這些類並能夠根據類填充並返回這些類的解決方案:

首先,我添加了一個bindings.xjb文件,該文件將生成所包含的類(在此示例中為數據庫和隊列)

<jaxb:bindings
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:globalBindings localScoping="toplevel"/>
</jaxb:bindings>

但是,JAXB不能使用數據庫或隊列類來解組,只能使用配置類(在這里我可能會錯過一些東西)。 我可以

JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller um = context.createUnmarshaller();
Configuration conf = (Configuration) um.unmarhal(xmlFile);

但不是

JAXBContext context = JAXBContext.newInstance(Database.class);
Unmarshaller um = context.createUnmarshaller();
Database db = (Database) um.unmarhal(xmlFile);

但是,因為我可以通過在Configuration對象的實例上調用getDatabase()來獲取數據庫對象,所以也可以使用反射使它通用(使此代碼高速緩存結果位於適當的位置是另一項練習):

    T item = null;
    try {
        JAXBContext context = JAXBContext.newInstance(Configuration.class);
        Unmarshaller um = context.createUnmarshaller();
        Configuration conf = (Configuration) um.unmarshal(xmlFile);
        Method[] allMethods = Configuration.class.getDeclaredMethods();
        for (Method method : allMethods)
        {
            if (method.getReturnType().equals(clazz))
            {
                item = (T) method.invoke(conf);
                break;
            }
        }
    } catch (JAXBException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new ConfigException("Failure detected while loading configuration", e);
    }
    return item;

我不確定這是最好的解決方案(我昨天才開始使用JAXB),但似乎實現了我的目標。

該特定的XML將對應於具有類DatabaseQueue屬性的Configuration類。 這不是您要找的東西嗎?

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Configuration {

    private Database database;
    private Queue queue;

}

我正在用問題中討論的解決方案回答這個問題。 這符合我的要求:


經過一些試驗,我找到了一種生成這些類並能夠根據類填充並返回這些類的解決方案:

首先,我添加了一個bindings.xjb文件,該文件將生成所包含的類(在此示例中為數據庫和隊列)

<jaxb:bindings
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    version="2.1">
    <jaxb:globalBindings localScoping="toplevel"/>
</jaxb:bindings>

但是,JAXB不能使用數據庫或隊列類來解組,只能使用配置類(在這里我可能會錯過一些東西)。 我可以

JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller um = context.createUnmarshaller();
Configuration conf = (Configuration) um.unmarhal(xmlFile);

但不是

JAXBContext context = JAXBContext.newInstance(Database.class);
Unmarshaller um = context.createUnmarshaller();
Database db = (Database) um.unmarhal(xmlFile);

但是,因為我可以通過在Configuration對象的實例上調用getDatabase()來獲取數據庫對象,所以也可以使用反射使它通用(使此代碼高速緩存結果位於適當的位置是另一項練習):

    T item = null;
    try {
        JAXBContext context = JAXBContext.newInstance(Configuration.class);
        Unmarshaller um = context.createUnmarshaller();
        Configuration conf = (Configuration) um.unmarshal(xmlFile);
        Method[] allMethods = Configuration.class.getDeclaredMethods();
        for (Method method : allMethods)
        {
            if (method.getReturnType().equals(clazz))
            {
                item = (T) method.invoke(conf);
                break;
            }
        }
    } catch (JAXBException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
        throw new ConfigException("Failure detected while loading configuration", e);
    }
    return item;

這使我可以通過傳遞Database.class來獲得未編組的數據庫,而無需為以前的配置參數硬編碼方法。 然后,可以在需要時將其注入,而無需注入整個未編組的XML文件。

步驟1:創建3個類configuration.java,database.java,queue.java

配置文件

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "configuration")
public class configuration{

  @XmlElement
  private database db;
  @XmlElement
  private queue q;
  ...
}

@XmlAccessorType(XmlAccessType.FIELD)
public class database{
  @XmlElement
  private String host;
  @XmlElement
  private String port;
....
}

-------------------------

    InputStream xmlStream = new FileInputStream(config.xml);
    JAXBContext jaxbContext = JAXBContext.newInstance(configuration.class, database.class,queue.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
                    configuration config= (configuration) jaxbUnmarshaller.unmarshal(xmlStream);

    config.getDatabase().getHost(); //returns the host
    config.getDatabase().getPort(); //returns the port

------------------------------------

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM