JaxB marhsalling使用接口 [英] JaxB marhsalling using interfaces

查看:85
本文介绍了JaxB marhsalling使用接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下类,我希望能够基于一个接口动态生成xml,改变实现......这是可能的......我试过运气不好......

I have the following class, i want to be able to produce xml dynamically based ona an interface, with changing implementations... is that possible... i have tried with little luck...

@xmlRootElement
public class Vehicles {
   private String id;

   private List<VehicleType> types;


   .... various setters and getters...
   ... with annotated getters...

}

public interface VehicleType {
   public String getName();
}

public Car implements VehicleType {

    private String name;
    private String wheels;

    ...various constructors...

    @XmlElement
    public String getName() {
      return name;
    }

    @XmlElement
    public String getWheels() {
      return wheels;
    }

 }

public Motorbike implements VehicleType {

    private String name;
    private String exhaust;

    ...various constructors...

    @XmlElement
    public String getName() {
      return name;
    }

    @XmlElement
    public String getExhaust() {
      return exhaust;
    }

 }

我希望车辆的marshlling到产生以下输出:

I want the marshlling of Vehicles to produce the following output:

<vehicles>
   <types>
     <car>
        ..car specific elements
     </car>
     <motorbike>
        .. mototrbike specific elements
     <motorbike>
   </types>
</vehicles> 

车辆类无法了解实现,或者存在哪些......它只知道接口,这里我真的用作标记界面..允许我在运行时填充具有不同实现的列表...

The vehicles class cannot know about the implementations, or which ones exist.. it only knows about the interface, which here im using as a marker interface really.. to allow me to populate a list with different implementations at runtime...

无论如何我可以得到jaxb是将输出呈现为xml,而父母确实知道实现?

Is there anyway i can get jaxb be to render the output as xml with out the parent really knowing about the implementations?

推荐答案

注意:我是 EclipseLink JAXB(MOXy) 的主管和 JAXB(JSR-222) 专家的成员group。

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

以下内容不适用于JAXB参考实现,但可以使用EclipseLink JAXB(MOXy)。

The following will not work with the JAXB reference implementation but will work with EclipseLink JAXB (MOXy).

JAVA模型

下面是一个表示为int的简单域模型erfaces。我们将使用 @XmlType 批注指定工厂类来创建这些接口的具体impl。这将需要满足解组(参见: http:// blog .bdoughan.com / 2011/06 / jaxb-and-factory-methods.html

Below is a simple domain model represented as interfaces. We will use the @XmlType annotation to specify a factory class to create concrete impls of these interfaces. This will be required to satisfy unmarshalling (see: http://blog.bdoughan.com/2011/06/jaxb-and-factory-methods.html).

客户

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlType(
    propOrder={"name", "address"},
    factoryClass=Factory.class, 
    factoryMethod="createCustomer")
public interface Customer {

    String getName();
    void setName(String name);

    Address getAddress();
    void setAddress(Address address);

}

地址

import javax.xml.bind.annotation.XmlType;

@XmlType(factoryClass=Factory.class, factoryMethod="createAddress")
public interface Address {

    String getStreet();
    void setStreet(String street);

}

工厂

下面是返回接口具体impls的工厂方法。这些是在解组操作期间建立的动力。为了防止需要真正的类,我将利用代理对象。

Below is the factory method that returns concrete impls of the interfaces. These are the impls that will be built during an unmarshal operation. To prevent requiring real classes I will leverage Proxy objects.

import java.lang.reflect.*;
import java.util.*;

public class Factory {

    public Customer createCustomer() {
        return createInstance(Customer.class);    }

    public Address createAddress() {
        return createInstance(Address.class);
    }

    private <T> T createInstance(Class<T> anInterface) {
        return (T) Proxy.newProxyInstance(anInterface.getClassLoader(), new Class[] {anInterface}, new InterfaceInvocationHandler());
    }

    private static class InterfaceInvocationHandler implements InvocationHandler {

        private Map<String, Object> values = new HashMap<String, Object>();

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String methodName = method.getName();
            if(methodName.startsWith("get")) {
                return values.get(methodName.substring(3));
            } else {
                values.put(methodName.substring(3), args[0]);
                return null;
            }
        }

    }
}

jaxb.properties

要使此演示生效,您需要将MOXy指定为JAXB提供程序。这是通过带有以下条目的 jaxb.properties 文件完成的(参见: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

To get this demo to work you will need to specify MOXy as your JAXB provider. This is done via a jaxb.properties file with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

DEMO CODE

在下面的演示代码中,我们通过了任意实现要编组的接口。

In the demo code below we pass an arbitrary implementation of the interfaces to be marshalled.

演示

import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        AddressImpl address = new AddressImpl();
        address.setStreet("123 A Street");

        CustomerImpl customer = new CustomerImpl();
        customer.setName("Jane Doe");
        customer.setAddress(address);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }

}

输出

以下是运行演示代码的输出:

Below is the output from running the demo code:

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <name>Jane Doe</name>
   <address>
      <street>123 A Street</street>
   </address>
</customer>

这篇关于JaxB marhsalling使用接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆