【问题标题】:How to customise the XML output of a Jersey JAXB serialisation如何自定义 Jersey JAXB 序列化的 XML 输出
【发布时间】:2011-08-12 01:11:28
【问题描述】:

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

【问题讨论】:

    标签: jaxb jersey xmlserializer


    【解决方案1】:

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

    1) 创建了一个 JaxbFactory,它配置并返回一个自定义编组器(顺便说一句,解组器也是如此)。我省略了下面的 getters/and unmarshalling 设置...

    //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 中,我所要做的就是实例化资源提供者。反过来,它会从工厂抢走 marshaller。

    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 非常简单。一旦我开始沿着这条路走下去,泽西岛就从脑残容易变成了体面的困难。大部分困难是从网上各种帖子中找出所有细节。希望这将帮助您走得更远,更快。 :-)

    【讨论】:

      猜你喜欢
      • 2011-05-08
      • 2019-06-26
      • 1970-01-01
      • 2010-10-05
      • 2011-04-30
      • 1970-01-01
      • 2010-10-13
      • 2012-06-28
      • 1970-01-01
      相关资源
      最近更新 更多