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



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

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

1)创建了一个JaxbFactory,它配置并返回一个自定义编组程序(顺便说一句,也包括编组程序)。我省略了下面的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)工厂类对Jersey不"可见"。为了使其可见,我创建了一个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部分是使这一切结合在一起的最后一个关键齿轮。

希望有帮助。我花了太多时间来挖掘这些信息。在我想让Jersey进行适当的xml模式验证(以及对模式无效的输入进行适当的错误报告)之前,它非常简单。一旦我走上这条路,泽西就从脑残简单变成了相当困难。最大的困难是从网上各种各样的帖子中找出所有的细节。希望这能帮助你走得更远,更快。: -)

最新更新