遇到问题
今天springboot项目打包时,突然失败提示程序包com.sun.xml.internal.ws.util
不存在,反复时了几次都不成,Idea编辑器里正常显示,且启动没有报错,但是打包编译失败。经过我的一顿排查操作,将pom.xml文件中的spring-boot-maven-plugin
更换为maven-compiler-plugin
后解决了,问题原因是电脑环境变量中配置jdk版本里不包含这个工具包,而IDEA编辑器里自带这个包,虽然我在IDEA中配置的不是自带JDK
,而是电脑中安装的JDK
。IDEA依然能正常引用这个工具包,正常运行,但是使用maven
时,则因为使用的时环境中JDK
,导致因为缺少包的依赖,而打包失败!
结论:
该问题的根本原因是 Java 11 及更高版本中移除了 com.sun.xml.internal.*
等内部 API,而项目的某些依赖可能仍然在使用这些已废弃的类。spring-boot-maven-plugin
默认使用项目配置的 JDK 编译选项,可能会暴露兼容性问题;而 maven-compiler-plugin
则可能隐式地使用了不同的编译器设置或默认值,从而避免了该问题。
详细展开:
1. 错误原因:com.sun.xml.internal.ws.util
已被移除
- 在 Java 9 及更高版本中,Oracle 开始对 JDK 内部实现(如
com.sun.*
包)进行模块化和清理。 - 特别是从 Java 11 开始,
com.sun.xml.internal.*
被完全移除,不再作为标准库的一部分。 - 如果项目中某个依赖(例如某些旧版本的 XML 或 WebService 相关库)仍然引用了这些类,就会导致编译或运行时错误。
2. 插件行为差异
-
spring-boot-maven-plugin
:- 主要用于构建和打包 Spring Boot 应用程序。
- 它会基于项目的
pom.xml
配置来执行任务,并严格遵循 Maven 的编译规则。 - 如果项目中存在不兼容的依赖,
spring-boot-maven-plugin
会在打包阶段暴露这些问题。
-
maven-compiler-plugin
:- 专注于编译源代码。
- 默认情况下,它可能会忽略某些编译警告或依赖冲突,尤其是在未显式配置编译选项时。
- 这可能导致问题被掩盖,表面上看起来打包成功,但实际上可能存在潜在隐患。
3. 解决方案
以下是几种解决方法,建议根据实际情况选择:
方法一:升级相关依赖
- 检查项目的依赖树(通过
mvn dependency:tree
),找到引用com.sun.xml.internal.*
的依赖。 - 将这些依赖升级到支持 Java 11+ 的版本。例如:
- 如果使用的是
jaxb-api
或其他 XML 处理库,请确保升级到最新版本。 - 示例:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency>
- 如果使用的是
方法二:添加外部依赖
- 如果无法升级依赖,可以手动引入替代库以解决缺失的类。例如:
<dependency> <groupId>com.sun.xml.ws</groupId> <artifactId>rt</artifactId> <version>2.3.3</version> </dependency>
方法三:调整编译选项
- 在
maven-compiler-plugin
中显式配置编译参数,确保与spring-boot-maven-plugin
的行为一致。 - 示例:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>11</source> <target>11</target> <compilerArgs> <arg>--add-modules=java.xml.bind</arg> </compilerArgs> </configuration> </plugin> </plugins> </build>
方法四:降级 JDK 版本(不推荐)
- 如果项目确实需要使用旧版依赖,可以考虑暂时降级到 JDK 8。但这不是长期解决方案,因为 JDK 8 的支持周期已经结束。
总结:
出现“程序包 com.sun.xml.internal.ws.util
不存在”的问题是因为某些依赖引用了已被移除的内部 API。spring-boot-maven-plugin
更严格地暴露了这些问题,而 maven-compiler-plugin
可能暂时掩盖了它们。建议优先升级相关依赖或引入替代库,以确保项目的兼容性和稳定性。后续,我去除项目中了程序包 com.sun.xml.internal.ws.util
的依赖,更改回来了spring-boot-maven-plugin
,因为发现使用 maven-compiler-plugin
打包编译,mybatis接口类的参数必须使用 @Param 注解,否则包sql参数匹配错误,于是我选择了改动量小的方式,去掉了 com.sun.xml.internal.ws.util
的依赖!
补充知识
maven-compiler-plugin和spring-boot-maven-plugin的区别
简介
maven-compiler-plugin
是 Maven 的内置插件,用于编译 Java 源代码;而 spring-boot-maven-plugin
是 Spring Boot 提供的插件,专注于构建和打包 Spring Boot 应用程序。
详细展开:
1. maven-compiler-plugin
- 功能:主要用于编译项目中的 Java 源代码。
- 作用范围:适用于任何基于 Maven 构建的 Java 项目。
- 主要任务:
- 编译项目的源代码(
src/main/java
)。 - 编译测试代码(
src/test/java
)。
- 编译项目的源代码(
- 配置示例:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>17</source> <target>17</target> </configuration> </plugin> </plugins> </build>
- 特点:与 Java 版本相关,通常用来指定 JDK 的编译版本。
2. spring-boot-maven-plugin
- 功能:专门为 Spring Boot 项目设计,用于构建和打包 Spring Boot 应用程序。
- 作用范围:仅适用于 Spring Boot 项目。
- 主要任务:
- 打包 Spring Boot 应用程序为可执行的 JAR 或 WAR 文件。
- 支持运行 Spring Boot 应用程序(如通过
mvn spring-boot:run
)。 - 提供重新打包(repackage)功能,将依赖项嵌入到最终的 JAR/WAR 文件中。
- 配置示例:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
- 特点:专注于 Spring Boot 的生命周期管理,简化了应用程序的构建和运行。
区别总结:
特性 | maven-compiler-plugin | spring-boot-maven-plugin |
---|---|---|
主要功能 | 编译 Java 源代码 | 构建和打包 Spring Boot 应用 |
适用范围 | 所有 Maven 项目 | 仅限 Spring Boot 项目 |
核心任务 | 编译源代码和测试代码 | 打包可执行文件、运行应用 |
配置复杂度 | 简单,通常只设置 JDK 版本 | 较复杂,涉及 Spring Boot 配置 |
如果用户需要同时使用两者,通常会在同一个 pom.xml
文件中分别配置它们。