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

标签 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 序列化?

最佳答案

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

1) 创建了一个 JaxbFactory 来配置并返回一个自定义编码器(以及解码器,顺便说一句)。我省略了下面的 setter/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 部分是最后一个关键的 cog,它使这一切走到了一起。

希望有帮助。我花了太多时间来挖掘所有这些信息。在我希望 Jersey 进行适当的 xml 模式验证(以及模式无效输入的体面错误报告)之前,Jersey 非常简单。一旦我开始沿着这条路走下去,Jersey 就从脑残很容易变成了相当困难。大多数困难在于从各种在线帖子中找出所有细节。希望这能帮助你走得更远、更快。 :-)

关于jaxb - 如何自定义 Jersey JAXB 序列化的 XML 输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7034673/

相关文章:

java - 在gradle中或通过xjc下载复杂的架构/wsdl

java - com.sun.jersey.api.view.Viewable无法解析,它是从required.class间接引用的

java - JAXB 中的 XmlAdaptar

java - JAXB 在编码 java 时将 xmlns 添加到元素中

java - 如何响应 REST API 版本不匹配的警告?

java - 通过在 URL 中指定方法路由到特定的 HTTP 方法资源

c# xml serialization 自定义 elementName

c# - Xml Serializer 中的注释问题

c# - 未为嵌套元素生成 xmlns 属性

java - JAX-WS (JAXB) : How to marshall java. util.Date 到 xs :anyType as xs:date instead of xs:dateTime?