Java 11+Maven+JAXB:生成并复用XSD映射类的实现咨询
问题解答
1. 需求是否可实现?
完全可以实现,你的需求是JAXB代码生成的典型场景,通过绑定文件(Bindings) + 片段(Episodes) 机制就能解决公共类型重复生成的问题,同时保证包结构与XSD目录结构对应。
2. 是否可通过Java 11+Maven结合现有插件实现?
可以实现。由于Java 11移除了JDK内置的JAXB模块,需要手动引入JAXB依赖,配合官方的jaxb-maven-plugin即可完成配置。
具体实现方案
第一步:编写绑定文件(bindings.xml)
在src/main/resources下创建绑定文件,指定每个XSD对应的Java包名:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1"> <!-- 公共类型对应根包 --> <jaxb:bindings schemaLocation="xsdfolder/commontypes.xsd"> <jaxb:schemaBindings> <jaxb:package name="com.example.xsdfolder"/> </jaxb:schemaBindings> </jaxb:bindings> <!-- dir1下的XSD对应子包 --> <jaxb:bindings schemaLocation="xsdfolder/dir1/file1.xsd"> <jaxb:schemaBindings> <jaxb:package name="com.example.xsdfolder.dir1"/> </jaxb:schemaBindings> </jaxb:bindings> <!-- dir2下的XSD对应子包 --> <jaxb:bindings schemaLocation="xsdfolder/dir2/file2.xsd"> <jaxb:schemaBindings> <jaxb:package name="com.example.xsdfolder.dir2"/> </jaxb:schemaBindings> </jaxb:bindings> </jaxb:bindings>
第二步:配置Maven POM文件
核心思路是分三步执行代码生成:
- 先生成公共类型代码,并生成episode文件
- 生成dir1下的代码,引用公共类型的episode文件,避免重复生成
- 生成dir2下的代码,同样引用公共类型的episode文件
完整POM配置如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>jaxb-codegen-demo</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <jaxb.version>2.3.8</jaxb.version> </properties> <!-- Java 11需手动引入JAXB依赖 --> <dependencies> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>${jaxb.version}</version> <scope>runtime</scope> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> </dependencies> <build> <plugins> <!-- 官方JAXB Maven插件 --> <plugin> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-maven-plugin</artifactId> <version>${jaxb.version}</version> <executions> <!-- 1. 生成公共类型代码和episode文件 --> <execution> <id>gen-common-types</id> <goals> <goal>generate</goal> </goals> <configuration> <schemaDirectory>${project.basedir}/src/main/resources/xsdfolder</schemaDirectory> <schemaIncludes> <include>commontypes.xsd</include> </schemaIncludes> <bindingDirectory>${project.basedir}/src/main/resources</bindingDirectory> <bindingIncludes> <include>bindings.xml</include> </bindingIncludes> <!-- 生成episode文件供后续模块引用 --> <generateEpisode>true</generateEpisode> <outputDirectory>${project.build.directory}/generated-sources/xjc</outputDirectory> </configuration> </execution> <!-- 2. 生成dir1下的代码,引用公共类型的episode --> <execution> <id>gen-dir1-types</id> <goals> <goal>generate</goal> </goals> <configuration> <schemaDirectory>${project.basedir}/src/main/resources/xsdfolder/dir1</schemaDirectory> <schemaIncludes> <include>file1.xsd</include> </schemaIncludes> <bindingDirectory>${project.basedir}/src/main/resources</bindingDirectory> <bindingIncludes> <include>bindings.xml</include> </bindingIncludes> <!-- 引入公共类型的episode,避免重复生成 --> <episodeFiles> <episodeFile>${project.build.directory}/generated-sources/xjc/META-INF/sun-jaxb.episode</episodeFile> </episodeFiles> <outputDirectory>${project.build.directory}/generated-sources/xjc</outputDirectory> </configuration> </execution> <!-- 3. 生成dir2下的代码,引用公共类型的episode --> <execution> <id>gen-dir2-types</id> <goals> <goal>generate</goal> </goals> <configuration> <schemaDirectory>${project.basedir}/src/main/resources/xsdfolder/dir2</schemaDirectory> <schemaIncludes> <include>file2.xsd</include> </schemaIncludes> <bindingDirectory>${project.basedir}/src/main/resources</bindingDirectory> <bindingIncludes> <include>bindings.xml</include> </bindingIncludes> <episodeFiles> <episodeFile>${project.build.directory}/generated-sources/xjc/META-INF/sun-jaxb.episode</episodeFile> </episodeFiles> <outputDirectory>${project.build.directory}/generated-sources/xjc</outputDirectory> </configuration> </execution> </executions> </plugin> <!-- 将生成的代码加入编译路径 --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <version>3.3.0</version> <executions> <execution> <id>add-generated-source</id> <phase>generate-sources</phase> <goals> <goal>add-source</goal> </goals> <configuration> <sources> <source>${project.build.directory}/generated-sources/xjc</source> </sources> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
关键说明
- 绑定文件:明确映射XSD到Java包,确保生成的类结构与XSD目录结构一致。
- Episode机制:公共类型生成时生成的
sun-jaxb.episode文件会记录已生成的类型信息,后续生成dir1/dir2代码时,JAXB会读取该文件,直接导入公共类型而不重复生成。 - Java 11适配:通过手动引入JAXB相关依赖,配合适配Java 11的
jaxb-maven-plugin版本(2.3.x及以上),解决Java 11移除JAXB模块的问题。
内容的提问来源于stack exchange,提问作者lux_piromani
相关产品推荐
相关产品推荐

