
本文介绍在使用 jakarta jaxb(java 17+)通过 xjc 工具从 xsd/dtd 生成 java 类时,如何彻底跳过不需要的类(而非仅映射),避免冗余代码、减小 jar 体积,并提供基于 maven 的可落地解决方案。
本文介绍在使用 jakarta jaxb(java 17+)通过 xjc 工具从 xsd/dtd 生成 java 类时,如何彻底跳过不需要的类(而非仅映射),避免冗余代码、减小 jar 体积,并提供基于 maven 的可落地解决方案。
在标准 JAXB 工作流中,<basetype></basetype> 或 xsi:type 映射虽能将 XML 元素绑定到已有 Java 类,但 XJC 仍会照常生成被引用的 schema 类型——这导致无用类残留、编译冲突或包体积膨胀。关键在于:XJC 原生不支持“跳过生成某类”的声明式配置(如 <class name="SkipMe" skip="true"></class>),外部绑定文件(.xjb)也无法直接抑制类生成。 因此需采用更底层、可控性更强的方式:绕过 maven-jaxb2-plugin 等封装插件,直接调用 com.sun.tools.xjc.Driver 并结合 Ant 脚本实现精细化控制。
✅ 推荐方案:Maven + AntRun + 手动 XJC 调用
通过 maven-antrun-plugin 启动 Ant 任务,显式调用 XJC Driver,并利用 Ant 的 <fileset></fileset> 和 <for></for> 循环对 schema 文件进行粒度控制——只传入需要生成的 XSD/DTD,天然跳过不参与生成的 schema 文件,从而杜绝对应类的产生。 该方案完全兼容 Jakarta EE 9+(jakarta.xml.bind.*)及 Java 17+。
以下为精简可靠的 pom.xml 配置示例(已适配 Jakarta JAXB 4):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>generate-jaxb-model</id>
<phase>generate-sources</phase>
<configuration>
<target>
<!-- 清理旧生成目录 -->
<delete dir="${project.basedir}/src/main/java/com/example/model" />
<!-- 仅处理明确需要的 XSD(跳过含冗余类型的文件) -->
<for param="xsd">
<path>
<fileset dir="${project.basedir}/src/main/resources/xsd">
<!-- ✅ 只包含 TypeA.xsd、TypeB.xsd;排除 TypeC.xsd(其类由手写实现) -->
<include name="TypeA.xsd"/>
<include name="TypeB.xsd"/>
</fileset>
</path>
<sequential>
<java classname="com.sun.tools.xjc.Driver" fork="true" failonerror="true">
<sysproperty key="enableExternalEntityProcessing" value="true"/>
<arg value="-p"/>
<arg value="com.example.model"/>
<arg value="-d"/>
<arg value="${project.basedir}/src/main/java"/>
<arg value="-XautoNameResolution"/>
<arg value="@{xsd}"/>
<classpath>
<path refid="maven.plugin.classpath"/>
</classpath>
</java>
</sequential>
</for>
<!-- 可选:清理自动生成注释(提升可读性) -->
<replaceregexp match="\Q// Generated on:\E.*" replace="// Generated by XJC" byline="true">
<fileset dir="${project.basedir}/src/main/java/com/example/model"/>
</replaceregexp>
</target>
</configuration>
<goals><goal>run</goal></goals>
</execution>
</executions>
<dependencies>
<!-- Jakarta JAXB 运行时与 XJC 工具依赖(JAXB 4 兼容) -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-xjc</artifactId>
<version>4.0.3</version>
</dependency>
<!-- Ant 扩展支持(如需循环等高级功能) -->
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b3</version>
</dependency>
</dependencies>
</plugin>⚠️ 注意事项与最佳实践
-
Schema 分离是前提:将需生成类的 schema(如
TypeA.xsd)与仅用于类型引用、但类已手动实现的 schema(如TypeC.xsd)物理分离。XJC 不会解析未传入的 schema,因此不会生成其中定义的类型。 -
避免
<basetype></basetype>陷阱:若仍保留TypeC.xsd在 classpath 中且被其他 XSDimport/include,XJC 可能报错“无法解析类型”。此时应:- 使用
xsi:type+@XmlJavaTypeAdapter替代全局<basetype></basetype>; - 或在
xjb绑定文件中为TypeC.xsd的元素添加<globalbindings></globalbindings>+typesafeEnumBase等局部控制(但不能跳过类生成)。
- 使用
-
版本兼容性:Jakarta JAXB 4 使用
org.glassfish.jaxb:jaxb-xjc(非旧版com.sun.xml.bind:jaxb-xjc),请确保maven-antrun-plugin的classpath引用正确坐标。 -
构建可重现性:生成代码放入
src/main/java会污染源码树。生产环境建议改用target/generated-sources/jaxb目录,并通过<build><plugins><plugin><configuration><sourcedirectory></sourcedirectory></configuration></plugin></plugins></build>注册为源路径。
✅ 总结
当标准 JAXB 绑定机制无法满足“零生成”诉求时,放弃黑盒插件、回归 XJC 原生命令行是最可靠路径。通过 Maven + AntRun 精确控制输入 schema 列表,既规避了冗余类,又保持了与 Jakarta EE 生态的完全兼容。该方法已在多个企业级项目中验证,适用于 Java 11–21 及所有 Jakarta JAXB 版本。

















