我有以下课程,我希望能够基于接口,不断变化的实现动态生成xml。
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望车辆编组产生以下输出:
<vehicles>
<types>
<car>
..car specific elements
</car>
<motorbike>
.. mototrbike specific elements
<motorbike>
</types>
</vehicles>
Run Code Online (Sandbox Code Playgroud)
Vehicles类无法知道实现或存在的实现..它只知道接口,在这里我实际上将其用作标记接口..允许我在运行时填充具有不同实现的列表...
无论如何,我可以让jaxb将输出渲染为xml,而无需父母真正了解实现吗?
注意:我是EclipseLink JAXB(MOXy)的负责人,并且是JAXB(JSR-222)专家组的成员。
以下内容不适用于JAXB参考实现,但适用于EclipseLink JAXB(MOXy)。
JAVA模型
以下是表示为接口的简单域模型。我们将使用@XmlType批注指定一个工厂类来创建这些接口的具体实现。这将满足解组的要求(请参阅: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);
}
Run Code Online (Sandbox Code Playgroud)
地址
import javax.xml.bind.annotation.XmlType;
@XmlType(factoryClass=Factory.class, factoryMethod="createAddress")
public interface Address {
String getStreet();
void setStreet(String street);
}
Run Code Online (Sandbox Code Playgroud)
厂
下面是返回接口具体含义的工厂方法。这些是将在非海警行动期间建立的干扰。为了避免需要真实的类,我将利用Proxy对象。
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;
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
jaxb.properties
要使此演示正常工作,您需要将MOXy指定为JAXB提供程序。这是通过jaxb.properties带有以下条目的文件完成的(请参阅:http : //blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Run Code Online (Sandbox Code Playgroud)
演示代码
在下面的演示代码中,我们传递了将要编组的接口的任意实现。
演示版
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Run Code Online (Sandbox Code Playgroud)
输出量
以下是运行演示代码的输出:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4450 次 |
| 最近记录: |