深入理解Maven依赖管理:MySQL驱动版本冲突案例分析
站长
· 阅读数 4
背景介绍
- 我有一个 common 工程,引入了一个版本较高的 MySQL 驱动依赖
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
- IDEA 中把 common 工程使用
maven
插件deploy
到远程私有maven仓库 - 另一个
maven
工程A中引入了该common包
<dependency>
<groupId>com.demo</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
- 由于工程A需要使用版本较低的MySQL驱动,所以又引入了一个低版本MySQL驱动依赖(在common包依赖的下方,划重点!!!)
<dependency>
<groupId>com.demo</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
问题呈现
- 运行工程,调用包含数据库操作的接口,我期望使用低版本依赖,实际使用的是高版本依赖。控制台打印由于MySQL驱动和数据库版本不匹配导致的异常信息
java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110) ~[mysql-connector-j-8.0.31.jar:8.0.31]
可以看到,异常信息来自高版本的MySQL驱动包[mysql-connector-j-8.0.31.jar:8.0.31]
问题分析
- 目前工程A中引入了两个MySQL驱动依赖,一个是直接引入的,另一个是通过common包间接引入的,
scope
标签都未指定,默认为compile
- 在工程A的
pom.xml
文件中引入依赖的顺序是,先引入common包,后引入低版本MySQL驱动包,如背景介绍中第四点所示
maven 解析依赖规则
- 路径最短者优先:路径距离是从项目开始到依赖项的距离,直接依赖的距离为0,间接依赖的距离为1,以此类推。路径最短的依赖项会被优先使用
- 首次声明者优先:在POM文件中首次声明的依赖项会被优先使用
那么这两个规则哪个优先级更高呢?根据我的实践结果来看,显然第二条优先级更高。
解决办法
- 方式一:在工程A的
pom.xml
文件中排除高版本的依赖
<dependency>
<groupId>com.demo</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>mysql-connector-j</artifactId>
<groupId>com.mysql</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
- 方式二:调换common包和MySQL驱动包的引入顺序
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.demo</groupId>
<artifactId>common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>