这篇文章打算成为一个问题,但在其撰写过程中,我想出了一个解决方案,我想分享它。
我有一个 jax-ws Web 服务,其中一个操作只接受一个参数,可以说它称为 AnimalParameter。问题是客户可以用他喜欢的任何动物(一次一个)调用我的服务。动物是预定义的。我的目的是检索这个“AnicmalParameter”的内容并调用另一个 Web 服务服务,该服务实际上对每只动物都有一个操作。
我将 XmlElements 与继承结合使用作为动态绑定选择,以便用相同的 bean 捕获每只动物:
@XmlRootElement
public class AnimalParameter implements Serializable {
@XmlElements({
@XmlElement(name = "dog", type=Dog.class ),
@XmlElement(name = "cat", type=Cat.class )
})
protected Animal animal;
}
在我的情况下,客户一次将调用一只动物。所以xml会像:
<animalParameter>
<dog>
...
</dog>
</animalParameter>
或者 :
<animalParameter>
<cat>
...
</cat>
</animalParameter>
通过执行以下操作将整个动物容器编组为字符串相当容易:
final Writer xmlString = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(AnimalParameter.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(animalParameter, xmlString);
我的问题是我只想用我收到的动物(狗或猫不是整个参数)打印一个 xml,这似乎非常困难,因为在编译时我不知道我的网络服务将被调用的动物和。因此,即使我上面的 bean 也能够将请求与 dog 和 cat 绑定,你如何在没有根元素的情况下将其编组为 xml。我试图在我的 bean 中放置一个方便的方法:
@XmlRootElement
public class AnimalParameter implements Serializable
.
.
.
@XmlElement
public Animal getAnimal(){
return animal;
}
}
并使用:
JAXBContext jaxbContext = JAXBContext.newInstance(Animal.class);
jaxbMarshaller.marshal(animalParameter.getAnimal(), xmlString);
打印的xml是:
<animal>...</animal> and not the desired <cat>...</cat> or <dog>...</dog>
我的理解是,JAXB 用于将 xml 绑定到 java 类/字段的绑定元数据没有存储在任何地方,它只是运行时执行的代码。所以java字段“animal”真的不知道它真正绑定到哪个xml节点。
我用这个解决了:
String animalName = animalParameter.getAnimal().getClass().getSimpleName();
JAXBContext jaxbContext = JAXBContext.newInstance(Animal.class);
jaxbMarshaller.marshal(new JAXBElement<Operation>(new QName(animalName), Animal.class, animalParameter.getAnimal()), stringWriter);