gpt4 book ai didi

java - 为什么在 Jaxb2Marshaller 中需要检查根元素?

转载 作者:搜寻专家 更新时间:2023-10-31 19:41:46 26 4
gpt4 key购买 nike

我正在使用 Jaxb2Marshaller 通过 spring @ResponseBody 注释编码 Java bean。对于 JSON 编码(marshal)处理工作正常。但是对于 xml,我不断收到 HTTP 406 响应。在 Jaxb2Marshaller 类中稍微挖掘一下就会发现它会检查 @XmlRootElement 是否有界类(请参见下面的代码片段)。

从 xsd 生成 java 代码时,我的 pojo 不包含 @XmlRootElement,并且 AnnotationMethodHandlerAdapter 未识别正确的消息转换器,最终导致 406。

我没有从 xsd 自动生成 java 代码,而是创建了自己的 pojo 类并使用了@XmlRootElement。然后编码工作正常。

我想了解为什么让@XmlRootElement 检查有界类很重要。或者以任何方式将元素指定为 xsd 中的@XmlRootElement。

来自 Jaxb2Marshaller 的代码片段:

public boolean supports(Class clazz) {
return supportsInternal(clazz, true);
}

private boolean supportsInternal(Class<?> clazz, boolean checkForXmlRootElement) {
if (checkForXmlRootElement && clazz.getAnnotation(XmlRootElement.class) == null) {
return false;
}
if (clazz.getAnnotation(XmlType.class) == null) {
return false;
}
if (StringUtils.hasLength(getContextPath())) {
String className = ClassUtils.getQualifiedName(clazz);
int lastDotIndex = className.lastIndexOf('.');
if (lastDotIndex == -1) {
return false;
}
String packageName = className.substring(0, lastDotIndex);
String[] contextPaths = StringUtils.tokenizeToStringArray(getContextPath(), ":");
for (String contextPath : contextPaths) {
if (contextPath.equals(packageName)) {
return true;
}
}
return false;
}
else if (!ObjectUtils.isEmpty(classesToBeBound)) {
return Arrays.asList(classesToBeBound).contains(clazz);
}
return false;
}

编辑:Blaise 回答帮助我解决了@XmlRootElement 问题。但是,如果有人知道为什么需要检查 XmlRootElement 的任何信息,那将是一个很好的信息。

最佳答案

为什么检查@XmlRootElement 注解

Spring 在将对象编码为 XML 时需要一个根元素。 JAXB 提供了两种机制来执行此操作:

  1. @XmlRootElement 注释
  2. 将根对象包装在 JAXBElement 的实例中。

由于对象没有包装在 JAXBElement 中,Spring 确保满足其他条件。

如何生成@XmlRootElement

JAXB 将为 XML 模式中的所有全局元素生成一个 @XmlRootElement 注释。以下将导致一个@XmlElement:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="foo">
<xsd:complexType>
...
</xsd:complextType>
</xsd:element>
</xsd:schema>

没有生成@XmlRootElement时

不会为全局类型生成@XmlRootElement 注释。

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="foo" type="foo"/>
<xsd:complexType name="foo">
...
</xsd:complexType>
</xsd:schema>

相反,与全局类型关联的全局元素以@XmlElementDecl 注释的形式在 ObjectFactory 类(使用@XmlRegistry 注释)中捕获。这些注解

package generated;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;


@XmlRegistry
public class ObjectFactory {

private final static QName _Foo_QNAME = new QName("", "foo");

public Foo createFoo() {
return new Foo();
}

@XmlElementDecl(namespace = "", name = "foo")
public JAXBElement<Foo> createFoo(Foo value) {
return new JAXBElement<Foo>(_Foo_QNAME, Foo.class, null, value);
}

}

@XmlElementDecl 注释提供与@XmlRootElement 类似的信息,可用于解码操作。 JAX-RS 实现可能不利用 @XmlElementDecl,但是因为编码操作需要将对象包装在 JAXBElement 对象中以提供根元素名称/命名空间。

关于java - 为什么在 Jaxb2Marshaller 中需要检查根元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4803464/

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