maven问题大集合

生产中常见的maven问题以及解决方法

1、maven依赖冲突问题

1.1、现象:

依赖冲突很经常是类包之间的间接依赖引起的。每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被 maven 间接引入进来,从而造成类包冲突

1.2、步骤:

排查Maven冲突的步骤:
检查依赖树:使用mvn dependency:tree命令检查项目的依赖树,查看是否有冲突。

排除依赖:如果发现特定的依赖冲突,使用<exclusions>标签排除不需要的传递依赖。

版本管理:在pom.xml中使用<dependencyManagement>来统一管理版本。

清理工程:使用mvn clean清理之前的构建结果。

重新构建:执行mvn install重新构建项目。

检查插件版本:确保pom.xml中指定的Maven插件版本是正确的,避免由于插件版本不匹配导致的问题。

更新Maven:确保使用的是最新版本的Maven,有时候旧版本的Maven可能会导致一些不可预见的问题。

检查环境:确保本地Maven仓库的状态良好,网络连接没有问题,并且所有的环境变量都设置正确。

如果以上步骤无法解决问题,可以考虑寻求更具体的帮助,比如在Maven社区、Stack Overflow等平台上提问。

1.3、case:

1.3.1、检查冲突:

通过 dependency:tree 是命令来检查版本冲突如下

[INFO] org.example:hello:jar:1.0-SNAPSHOT
[INFO] ± org.springframework:spring-context:jar:5.2.7.RELEASE:compile
[INFO] | ± (org.springframework:spring-aop:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)
[INFO] | ± org.springframework:spring-beans:jar:5.2.7.RELEASE:compile
[INFO] | | - (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for duplicate)
[INFO] | ± org.springframework:spring-core:jar:5.2.7.RELEASE:compile
[INFO] | | - org.springframework:spring-jcl:jar:5.2.7.RELEASE:compile
[INFO] | - org.springframework:spring-expression:jar:5.2.7.RELEASE:compile
[INFO] | - (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for duplicate)
[INFO] - org.springframework:spring-aop:jar:5.2.0.RELEASE:compile
[INFO] ± (org.springframework:spring-beans:jar:5.2.0.RELEASE:compile - omitted for conflict with 5.2.7.RELEASE)
[INFO] - (org.springframework:spring-core:jar:5.2.0.RELEASE:compile - omitted for conflict with 5.2.7.RELEASE)

omitted for duplicate 表示有 jar 包被重复依赖,最后写着 omitted for conflict with xxx 的,说明和别的 jar 包版本冲突了,而该行的 jar 包不会被引入。

​ 比如上面有一行最后写着 omitted for conflict with 5.2.7.RELEASE,表示 spring-core 5.2.0 版本不会被项目引用,而 spring-core 5.2.7 版本会被项目引用

1.3.2、解决冲突:

项目的 pom.xml 形如下:

 <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

通过查看依赖树,我们知道项目会引用 5.2.7.RELEASE 的 spring core jar 包,而不会引用 5.2.0 的 jar 包,如果我们想用 5.2.0 版本的 spring core 包,我们该如何做?

1.3.2.1、方法一

使用第一声明者优先原则

谁先定义的就用谁的传递依赖,即在 pom.xml 文件自上而下,先声明的 jar 坐标,就先引用该 jar 的传递依赖。因此我们如果要使用 5.2.0 版本的 spring core 包,我们可以改成如下声明:

<dependencies>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>5.2.0.RELEASE</version>
  </dependency>

  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.7.RELEASE</version>
  </dependency>

</dependencies>

然后查看依赖树mvn dependency:tree

[INFO] org.example:hello:jar:1.0-SNAPSHOT
[INFO] ± org.springframework:spring-aop:jar:5.2.0.RELEASE:compile
[INFO] | ± org.springframework:spring-beans:jar:5.2.0.RELEASE:compile
[INFO] | | - (org.springframework:spring-core:jar:5.2.0.RELEASE:compile - omitted for duplicate)
[INFO] | - org.springframework:spring-core:jar:5.2.0.RELEASE:compile
[INFO] | - org.springframework:spring-jcl:jar:5.2.0.RELEASE:compile
[INFO] - org.springframework:spring-context:jar:5.2.7.RELEASE:compile
[INFO] ± (org.springframework:spring-aop:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)
[INFO] ± (org.springframework:spring-beans:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)
[INFO] ± (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)
[INFO] - org.springframework:spring-expression:jar:5.2.7.RELEASE:compile
[INFO] - (org.springframework:spring-core:jar:5.2.7.RELEASE:compile - omitted for conflict with 5.2.0.RELEASE)

通过依赖树,我们可以看到项目已经引入 5.2.0 版本的 spring core 包。

1.3.2.2、方法二

**使用路径近者优先原则 **

即直接依赖级别高于传递依赖。因此我们可以在最先的 pom.xml 添加如下内容:

<dependencies>
   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>5.2.7.RELEASE</version>
   </dependency>

   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-aop</artifactId>
       <version>5.2.0.RELEASE</version>
   </dependency>

   <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-core</artifactId>
       <version>5.2.0.RELEASE</version>
   </dependency>
</dependencies>

然后通过工具查看如下,发现用的是5.2.0

img

1.3.2.3、方法三【推荐】

排除依赖

​ 排除依赖的方式有两种,一种是通过maven的插件实现(百度一下就知道这里不做赘述。),第二种是在maven的配置文件中来搞;下面我们来主要说下这种方式,具体如下:

 <dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
        <exclusions>
            <exclusion>
                <artifactId>spring-core</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
</dependencies>

这种就实现了,对5.2.7的排除,使用的是5.2.0的;下图也可以佐证:
img

*** 版本锁定***

使用 dependencyManagement 进行版本锁定,dependencyManagement 可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致。

如果我们项目中只想使用 spring core 5.2.0 的包,pom.xml 可以改为如下:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.7.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>

</dependencies>

则 在导入spring-core的依赖的时候会自动导入5.2.0的版本;如下图:

img

注:dependencyManagement 只是声明依赖,并不自动实现引入,因此子项目需要显示的声明需要用的依赖

2、依赖管理&传递问题

2.1、问题

项目结构复杂存在多级多pom文件的时候,管理不好会导致依赖传递不下去或者是版本混乱等问题。

2.2、排查

查看maven依赖树+pom文件

maven依赖树查询命令:mvn dependency:tree

2.3、解决方案

  • 新项目

    • 在立项初期就要确认好 jdk、maven、spring | springboot | other…技术栈的版本,然后统一管理。
  • 老项目

    • 搞清楚maven的依赖管理逻辑,然后添加响应的依赖即可
  • maven依赖管理

      1. dependencies:自动引入声明在dependencies里的所有依赖,并默认被所有的子项目继承。
    

    如果项目中不写依赖项,则会从父项目继承(属性全部继承)声明在父项目dependencies里的依赖项。

      2. dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要的依赖。
    

    如果不在子项目中声明依赖,是不会从父项目中继承的;

    只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;

    如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

    同时dependencyManagement让子项目引用依赖,而不用显示的列出版本号。

    Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号,实现所有子项目使用的依赖项为同一版本。

3、maven install 或者是maven package报错

3.1 、问题

由于maven的pom文件或者引入包导致打包或者编译失败。如下场景:

3.2、排查

maven中对于问题排查,提供了一个参数 [X],在执行install或者package的时候可以加上,能够看出来我们的maven的具体配置参数,来检查。如:

mvn -X package

这行命令可以在执行package命令的时候,打印出来详情。

如下:
在这里插入图片描述
在这里插入图片描述

如上一样,其实已经打出来我们需要的信息,说明source&target 的版本是1.5的

那我们检查下maven的pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mydatabase</artifactId>
    <version>1.1</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>21</java.version>
        <maven.compier.source>21</maven.compier.source>
        <maven.compier.target>21</maven.compier.target>
    </properties>

</project>

以上是我们的配置文件,发现文件里面是21,那我们想配置的其他例如编码都是ok的说明配置文件是生效的;那既然配置文件生效我们再来检查下对应的配置项发现compier错了,我们改成compiler试试。

3.3、解决方案

修改对应的配置,修改后为:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mydatabase</artifactId>
    <version>1.1</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>21</java.version>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
    </properties>

</project>

发现编译成功了:

在这里插入图片描述

我们在看看打印出来的日志:

看到日志内容也符合预期了,完美!

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值