使用maven-jaxb2-plugin结合episode时如何注册XmlAdapter
解决maven-jaxb2-plugin中Episode与XMLAdapter共存的问题
我之前也碰到过类似的坑,咱们一步步来排查和解决你的问题:
1. 先检查XSD里的xjc命名空间配置
你在XSD里加的<xjc:javaType>没生效,大概率是命名空间没正确引入。要在你的xs:schema标签里加上这两个配置:
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc"
比如完整的schema开头应该是:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:version="2.1" jaxb:extensionBindingPrefixes="xjc">
没有这些命名空间声明,XJC会直接忽略xjc:javaType这类扩展注解。
2. 调整插件执行顺序,把适配器绑定放在commonClasses的生成步骤里
你现在的问题是在引用commonClasses的两个XSD执行块里加了episode,但适配器绑定没生效。其实正确的姿势是:
- 第一个执行块:专门处理
commonClasses.xsd,在这里完成适配器绑定(不管是用XSD里的xjc:javaType还是单独的XJB文件),同时生成episode文件。这样生成的commonClasses枚举类已经带上了适配器配置,episode也会包含这个绑定信息。 - 后续两个执行块:只需要引用这个生成好的episode,不需要再加额外的绑定配置,就能直接复用带适配器的枚举类,不会重复生成,也不会有null转换的问题。
举个maven插件配置的例子:
<!-- 第一步:生成commonClasses并绑定适配器,同时生成episode --> <execution> <id>generate-common</id> <goals> <goal>generate</goal> </goals> <configuration> <schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory> <schemaIncludes> <include>commonClasses.xsd</include> </schemaIncludes> <generateEpisode>true</generateEpisode> <!-- 这里可以加XJB绑定文件,或者依赖XSD里的xjc注解 --> <bindingDirectory>${project.basedir}/src/main/resources/bindings</bindingDirectory> <bindingIncludes> <include>common-bindings.xjb</include> </bindingIncludes> </configuration> </execution> <!-- 第二步:引用common的episode,生成第一个业务XSD的类 --> <execution> <id>generate-service1</id> <goals> <goal>generate</goal> </goals> <configuration> <schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory> <schemaIncludes> <include>service1.xsd</include> </schemaIncludes> <extension>true</extension> <bindingDirectory>${project.build.directory}/generated-sources/xjc/generic/META-INF</bindingDirectory> <bindingIncludes> <include>generic.episode</include> </bindingIncludes> </configuration> </execution> <!-- 第三步:同理生成第二个业务XSD的类 --> <execution> <id>generate-service2</id> <!-- 配置和service1类似 --> </execution>
3. 用全局XJB绑定统一配置适配器
如果你的枚举类比较多,不想在每个XSD里加注解,可以写一个全局绑定文件(比如common-bindings.xjb),把适配器配置集中管理:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:common="http://your-common-namespace" jaxb:version="2.1" jaxb:extensionBindingPrefixes="xjc"> <!-- 绑定common命名空间下的foo枚举到自定义适配器 --> <jaxb:bindings schemaLocation="../xsd/commonClasses.xsd" node="/xs:schema"> <jaxb:bindings node="xs:simpleType[@name='foo']"> <xjc:javaType name="something.Foo" adapter="something.FooAdapter"/> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
把这个文件放在第一步的bindingIncludes里,生成commonClasses的时候就会把适配器绑定到枚举上,后续业务XSD引用episode时会自动继承这个配置。
4. 升级maven-jaxb2-plugin版本
一些旧版本的插件对episode和扩展绑定的兼容性不好,建议升级到2.5.0及以上的稳定版,很多这类兼容性bug都已经修复了。
最后要注意:确保你的适配器类something.FooAdapter在生成代码时是可访问的——如果是在同一个项目里,你可以先手动写好适配器类,或者把生成代码和写适配器分成两个maven阶段(比如先compile适配器,再生成JAXB类)。
内容的提问来源于stack exchange,提问作者Kristof Plennings
相关产品推荐
相关产品推荐

