为了学习如何使用@XmlAnyElement,我创建了以下测试服务:

@WebService(serviceName = "TestServices")
@Stateless()
public class TestServices {
    @WebMethod(operationName = "testMethod")
    public ServiceResult testMethod() {
        ServiceResult result = new ServiceResult();

        result.addObject(new SimpleObj(1, 2));
        result.addObject(new SimpleObj(3, 4));

        return result;
    }
}


SimpleObj是带有2个int字段的简单类。下面是ServiceResult类的代码:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({SimpleObj.class})
public class ServiceResult {
    @XmlAnyElement(lax = true)
    private List<Object> body;

    public void addObject(Object objToAdd) {
        if (this.body == null)
            this.body = new ArrayList();

        this.body.add(objToAdd);
    }

    // Getters and Setters
}


为了使用上述服务,我使用以下Main类创建了一个appclient:

public class Main {
    @WebServiceRef(wsdlLocation = "META-INF/wsdl/localhost_8080/TestServices/TestServices.wsdl")
    private static TestServices_Service service;
    private static TestServices         port;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        port = service.getAdminServicesPort();
        ServiceResult result = port.testMethod();

        for (Object o : result.getAny()) {
            System.out.println("TEST: " + o);
        }
    }
}


根据文档,使用@XmlAnyElement,解组器会急切地将此元素解组到JAXB对象。但是,我观察到的是JAXB仅将我的对象解析为JAXBElement,而不是一直解析为SimpleObj

如果您能告诉我如何从SimpleObj中获取ServiceResult,我将不胜感激。

更新:

下面是SimpleObj类:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SimpleObj {
    private int a;
    private int b;

    public SimpleObj() {}

    public SimpleObj(int a, int b) {
        this.a = a;
        this.b = b;
    }

    // Getters and Setters
}

最佳答案

我无法重现您所看到的问题。下面是一些直接与JAXB交互的演示代码。

import java.io.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(ServiceResult.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader xml = new StringReader("<serviceResult><simpleObj/><simpleObj/></serviceResult>");
        ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);

        for(Object item : result.getBody()) {
            System.out.println(item.getClass());
        }
    }

}


运行演示代码的输出显示,它是在SimpleObj注释的字段中的@XmlAnyElement(lax=true)实例。

class forum27871349.SimpleObj
class forum27871349.SimpleObj




更新1


  在旁注中,我阅读了您在@XmlAnyElement和
  我从未见过您必须在其中包含@XmlSeeAlso({SimpleObj.class})
  您的任何示例。


我不确定为什么我在示例中从未使用@XmlSeeAlso


  但是,就我而言,如果我没有这个,我会遇到错误
  说***类或它的任何超类在这种情况下是已知的。
  如果您还可以告诉我是否有办法让所有人
  消费者不使用@XmlSeeAlso的这些类中的


自己创建JAXBContext时,只需要包含您在@XmlSeeAlso批注中引用的所有内容,即可作为用来引导JAXBContext的类的一部分。

JAXBContext jc = JAXBContext.newInstance(ServiceResult.class, SimpleObj.class);


在您没有直接访问JAXBContext的JAX-WS(或JAX-RS)设置中,我建议像您一样使用@XmlSeeAlso批注。



更新#2


  关于@XmlAnyElement,从文档中,我认为
  解组器无法将元素解组到JAXB对象或
  JAXBElement对象,我至少会得到一个DOM节点。


当您使用@XmlAnyElement(lax=true)映射属性时,将发生以下情况:


如果元素对应于类的@XmlRootElement,则您将获得该类的实例。
如果该元素对应于@XmlElementDecl上某个类的ObjectFactory或带有@XmlRegistry注释的另一个类,则您将获得该类的实例,该实例包装在JAXBElement的实例中。
如果JAXB在元素和类之间没有关联,则它将把它转换为DOM Element


我将在下面举例说明。

对象工厂

import javax.xml.namespace.QName;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="simpleObjJAXBElement")
    public JAXBElement<SimpleObj> createSimpleObj(SimpleObj simpleObj) {
        return new JAXBElement<SimpleObj>(new QName("simpleObjJAXBElement"), SimpleObj.class, simpleObj);
    }

}


演示版

import java.io.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(ServiceResult.class, ObjectFactory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StringReader xml = new StringReader("<serviceResult><simpleObj/><unmapped/><simpleObjJAXBElement/></serviceResult>");
        ServiceResult result = (ServiceResult) unmarshaller.unmarshal(xml);

        for(Object item : result.getBody()) {
            System.out.println(item.getClass());
        }
    }

}


输出量

class forum27871349.SimpleObj
class com.sun.org.apache.xerces.internal.dom.ElementNSImpl
class javax.xml.bind.JAXBElement

10-04 20:28