gpt4 book ai didi

java - @XmlAnyElement 不会解码为特定的 Java 类型,而是停在 JAXBElement 处

转载 作者:太空宇宙 更新时间:2023-11-04 06:17:42 27 4
gpt4 key购买 nike

为了了解如何使用@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 类创建了一个应用程序客户端:

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

如果您能向我展示如何从 ServiceResult 中获取 SimpleObj,我将不胜感激。

更新:

下面是 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());
}
}

}

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

class forum27871349.SimpleObj
class forum27871349.SimpleObj
<小时/>

更新#1

On the side note, I've read your blog articles on @XmlAnyElement and I've never seen you had to include @XmlSeeAlso({SimpleObj.class}) in any of your examples.

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

However, in my case, if I don't have this, I would have the error saying Class *** nor any of its super class is known to this context. It'd be great if you could also show me if there is a way to make all of these classes known to the consumer without using @XmlSeeAlso

当您自己创建 JAXBContext 时,您只需包含在 @XmlSeeAlso 注释中引用的任何内容,作为用于引导 JAXBContext 的类的一部分。

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

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

<小时/>

更新#2

Regarding the @XmlAnyElement, from the documentation, I thought if the unmarshaller cannot unmarshal elements into JAXB objects or JAXBElement objects, I will at least get a DOM node.

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

  1. 如果该元素对应于类的 @XmlRootElement,那么您将获得该类的实例。
  2. 如果该元素对应于 ObjectFactory 上某个类的 @XmlElementDecl 或用 @XmlRegistry 注解的另一个类,那么您将获得包装在 JAXBElement 实例中的该类的实例。
  3. 如果 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

关于java - @XmlAnyElement 不会解码为特定的 Java 类型,而是停在 JAXBElement 处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27871349/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com