Spring非Boot应用迁移至Java17+Tomcat10后,Gradle中XJC任务抛出javax/xml/bind/JAXBException类找不到错误
嘿,我完全理解你现在的困扰——把非Boot的Spring应用从Java8+Tomcat8升级到Java17+Tomcat10后,你已经把项目里的javax依赖换成了jakarta,但Gradle里的XJC代码生成任务还是炸了,报找不到javax/xml/bind/JAXBException的错。这问题本质上是你当前用的XJC工具还是基于旧的javax规范构建的,和现在Jakarta EE的生态完全不兼容,下面给你一步步解决的方案:
第一步:替换所有JAXB相关依赖为Jakarta适配版本
你之前用的jaxb:xmlbind、jaxb:impl、jaxb:xjc这些都是旧的javax体系下的依赖,必须换成Jakarta对应的版本。在Gradle的dependencies块里做如下替换:
dependencies { // 项目依赖的Jakarta JAXB包 implementation 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.1' implementation 'com.sun.xml.bind:jaxb-impl:3.0.1' implementation 'jakarta.activation:jakarta.activation-api:2.0.1' // 给XJC任务单独配置的依赖组 jaxb 'jakarta.xml.bind:jakarta.xml.bind-api:3.0.1' jaxb 'com.sun.xml.bind:jaxb-impl:3.0.1' jaxb 'com.sun.xml.bind:jaxb-xjc:3.0.1' jaxb 'jakarta.activation:jakarta.activation-api:2.0.1' }
注意:版本号选3.x及以上的,因为从3.0开始JAXB正式迁移到Jakarta命名空间,完全取代了旧的javax包。
第二步:调整Gradle的XJC任务配置
原来的XJC任务默认会走旧的javax类路径,现在必须让它使用我们刚刚配置的Jakarta依赖。这里有两种方式:
方式一:直接修改原生Exec任务(如果你不想用插件)
先定义一个专门的jaxb配置组,然后在XJC任务里指定类路径和主类:
// 定义专门给XJC用的配置组 configurations { jaxb } task xjcProcessPayment(type: Exec) { classpath = configurations.jaxb // 指定Jakarta版本的XJC主类 mainClass = 'com.sun.tools.xjc.XJCFacade' args = [ '-d', sourcesDir, // 生成代码的输出目录 '-b', "${schema}/processPaymentBindings.jaxb", // JAXB绑定文件 '-Xdefault-value', '-extension', "${schema}/provider/gpos/processPayment/*.xsd" // 目标XSD文件路径 ] // 声明输出目录,让Gradle支持增量构建 outputs.dir sourcesDir }
方式二:用更省心的XJC Gradle插件(推荐)
使用org.unbroken-dome.xjc插件,它已经适配了Jakarta版本,配置更简洁。首先在settings.gradle里引入插件:
plugins { id 'org.unbroken-dome.xjc' version '2.0.0' }
然后在build.gradle里配置XJC任务:
xjc { // 指定使用的Jakarta JAXB版本 version = '3.0.1' // 关联我们定义的jaxb配置组 xjcClasspath = configurations.jaxb // 全局默认参数 defaultOptions { extension = true arg '-Xdefault-value' } } // 定义具体的代码生成任务 xjcGenerate { source = fileTree(dir: "${schema}/provider/gpos/processPayment", includes: ['*.xsd']) bindingFiles = file("${schema}/processPaymentBindings.jaxb") outputDir = file(sourcesDir) }
关键原因说明
Java17已经完全移除了JDK自带的JAXB模块,而且Tomcat10全面切换到Jakarta EE规范(把javax.*包改成了jakarta.*)。你的XJC任务之前依赖的是旧的javax版工具,它在运行时会尝试加载javax.xml.bind下的类,但现在你的项目类路径里只有jakarta.xml.bind的类,自然就会抛出找不到类的错误——换成Jakarta版本的XJC工具后,它会正确加载jakarta.xml.bind下的类,问题就解决了。
备注:内容来源于stack exchange,提问作者WowBow

