You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将公共类移至父包后JAXB解包映射失败问题求助

问题描述

我有多个对应不同版本(通过不同命名空间标识)的XSD文件,其中包含大量跨版本通用的复杂类型,使用XJC生成Java类时会产生大量重复类。为避免重复,我将公共类移至com.acme.common父包,并修改了ObjectFactory.java中的导入配置,但在解包XML时,仅根层级基本类型字段能映射成功,其他引用公共包类的字段为null或空值。若将所有类放在同一包下则映射正常。

生成JAXB类的命令如下:

xjc rixml-2_5.xsd -p com.acme.A -verbose -XautoNameResolution
xjc rixml-2_4.xsd -p com.acme.B -verbose -XautoNameResolution

获取JAXB上下文的代码如下:

private static final Class<?>[] classesToBeBound = new Class<?>[] {
            com.acme.A.ObjectFactory.class,
            com.acme.B.ObjectFactory.class };

    private static JAXBContext context;

    static {
        try {
            context = JAXBContext.newInstance(classesToBeBound);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }

请问是否可通过JAXB或其他Java库解决该问题?

解决方案

当然可以解决,核心是让JAXB正确识别跨包的公共类,以下是几种可行方案:

1. 修正JAXB上下文初始化,包含公共包类

你当前的classesToBeBound只包含了A、B包的ObjectFactory,但JAXB无法自动发现com.acme.common下的公共类,导致解包时无法映射这些类型的字段。需要把公共类也加入上下文初始化参数:

private static final Class<?>[] classesToBeBound = new Class<?>[] {
            com.acme.A.ObjectFactory.class,
            com.acme.B.ObjectFactory.class,
            // 添加公共包下的核心类,或直接加公共包的ObjectFactory(如果存在)
            com.acme.common.CommonType1.class,
            com.acme.common.CommonType2.class
            // 其他公共类依次添加
};

如果公共类较多,也可以直接指定包名初始化上下文(需确保包下有jaxb.index文件或ObjectFactory):

context = JAXBContext.newInstance("com.acme.A:com.acme.B:com.acme.common");

2. 生成类时直接指定公共类型的绑定(推荐,避免手动移类)

不要手动移动类,而是通过XJC的外部绑定文件(binding.xjb)提前指定公共类型的包路径,让XJC直接把跨版本通用的复杂类型生成到com.acme.common包,避免后续手动修改的问题。

示例binding.xjb内容:

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               jaxb:version="2.1">
    <!-- 绑定2_5版本XSD中的通用类型到公共包 -->
    <jaxb:bindings schemaLocation="rixml-2_5.xsd" node="/xsd:schema">
        <jaxb:bindings node="//xsd:complexType[@name='CommonType1']">
            <jaxb:class name="CommonType1" package="com.acme.common"/>
        </jaxb:bindings>
        <jaxb:bindings node="//xsd:complexType[@name='CommonType2']">
            <jaxb:class name="CommonType2" package="com.acme.common"/>
        </jaxb:bindings>
    </jaxb:bindings>
    <!-- 对2_4版本XSD做同样的绑定 -->
    <jaxb:bindings schemaLocation="rixml-2_4.xsd" node="/xsd:schema">
        <jaxb:bindings node="//xsd:complexType[@name='CommonType1']">
            <jaxb:class name="CommonType1" package="com.acme.common"/>
        </jaxb:bindings>
        <jaxb:bindings node="//xsd:complexType[@name='CommonType2']">
            <jaxb:class name="CommonType2" package="com.acme.common"/>
        </jaxb:bindings>
    </jaxb:bindings>
</jaxb:bindings>

生成类时指定绑定文件:

xjc rixml-2_5.xsd -p com.acme.A -verbose -XautoNameResolution -b binding.xjb
xjc rixml-2_4.xsd -p com.acme.B -verbose -XautoNameResolution -b binding.xjb

这样XJC会自动把指定的通用类型生成到公共包,且自动处理ObjectFactory的依赖,无需手动修改,解包时只要上下文包含三个包的类即可正常映射。

3. 使用MOXy替代原生JAXB(可选)

如果你愿意更换JAXB实现,Eclipse MOXy对跨包类型的识别更灵活,它支持通过jaxb.properties指定实现,且初始化上下文时能自动扫描关联的类,减少手动配置的麻烦。只需添加MOXy依赖,然后在每个包下添加jaxb.properties文件,内容为:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

之后初始化上下文的代码可以保持不变,MOXy会自动发现公共包的类。


内容的提问来源于stack exchange,提问作者Paras

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:40:19