如何自定义Jersey JAXB序列化的XML输出

时间:2011-08-12 01:11:29

标签: jaxb jersey xmlserializer

我在这里有一些@javax.xml.bind.annotation.Xml ...注释类用于RESt Web服务。 Jersey是在一个Spring托管的Web容器中设置的,Web服务正在返回格式良好的xml。我们使用maven-enunciate-plugin来记录Web服务并为返回的xml文档创建xsd。我现在想将文档xsd文件用作返回的xml文件中的schemaLocation,以便xml验证不会抱怨缺少定义。如何为此配置XML序列化?

1 个答案:

答案 0 :(得分:7)

如果我没记错的话,我必须做一些事情才能将命名空间标识符正确地写入我生成的XML中。

1)创建了一个JaxbFactory,它配置并返回一个自定义marshaller(和unmarshaller,BTW)。我省略了下面的getter /和解组设置......

//constructor
public JaxbFactory() throws Exception {
    context = JAXBContext.newInstance(ResourceDto.class);

    // Setup the marshaller
    marshaller = context.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, XmlMetadataConstants.XML_SCHEMA_LOCATION);  // this schema location is used in generating the schema-location property in the xml
}

2)泽西岛的工厂级别“不可见”。为了使它可见,我创建了一个MarshallerProvider。看起来像这样:

@Provider
public class ResourceJaxbMarshallerProvider implements ContextResolver<Marshaller> {
// injected by Spring
private ResourceJaxbFactory ResourceJaxbFactory;
private ResourceStatusJaxbFactory ResourceStatusJaxbFactory;


/*
 * ----------------------------------------
 * Setters (for Spring injected properties)
 * ----------------------------------------
 */
public void setResourceJaxbFactory(ResourceJaxbFactory ResourceJaxbFactory) {
    this.ResourceJaxbFactory = ResourceJaxbFactory;
}

public void setResourceStatusJaxbFactory(ResourceStatusJaxbFactory ResourceStatusJaxbFactory) {
    this.ResourceStatusJaxbFactory = ResourceStatusJaxbFactory;
}

/*
 * ------------------------
 * Interface Implementation
 * ------------------------
 */
public Marshaller getContext(Class<?> type) {
    if (type == ResourceDto.class)
        return ResourceJaxbFactory.getMarshaller();
    else if (type == ResourceStatusDto.class)
        return ResourceStatusJaxbFactory.getMarshaller();
    else
        return null;
}       
}

我使用Jersey / Spring Servlet将Jersey连接到Spring,因此任何由Spring创建的@Provider类都会被Jersey自动识别。在我的Spring applicationContext.xml中,我所要做的就是实例化资源提供者。反过来,它会从工厂中抓住编组员。

3)我发现另一件重要的事情是我必须在包含我的资源的根包中创建一个package-info.java文件。看起来像这样:

/*
 * Note that this file is critical for ensuring that our ResourceDto object is
 * marshalled/unmarshalled with the correct namespace.  Without this, marshalled
 * classes produce XML files without a namespace identifier
 */
@XmlSchema(namespace = XmlMetadataConstants.XML_SCHEMA_NAMESPACE, elementFormDefault = XmlNsForm.QUALIFIED) 
package com.yourcompany.resource;

import javax.xml.bind.annotation.XmlNsForm;

至少我认为这就是我需要做的一切,我不记得每件作品。我确实记得,package-info.java是最后一个让它们聚集在一起的关键因素。

希望有所帮助。我花了太多时间来挖掘所有这些信息。在我希望它进行适当的xml架构验证(以及架构无效输入的正确错误报告)之前,Jersey很诱人。一旦我开始沿着这条路开始,泽西从脑死亡变得容易到相当困难。大多数困难是从网上各种帖子中删除所有细节。希望这将有助于您更快,更快。 : - )