乐趣区

关于maven:maven多模块和依赖冲突问题汇总记录

目录

前言:

明天学习和总结了一下 maven 的相干知识点,发现一些比拟根底的货色竟然也会遗记,这里对于一些日常工作中可能会遇到的问题进行了一下汇总。

idea 怎么创立 maven 多 module 的我的项目

首先理解下面是多 module?

一句话概括就是:一个父模块作为版本控制多个子模块,子模块负责接入到父模块当中作为整个我的项目的过程。

多 Module 治理我的项目的几种形式:

  1. 依照单模块拆分为多个子模块,比方将 MVC 三层架构拆分为 xxx-service,xxx-dao,xxx-model,不过这种形式个人感觉比拟二,目前以业务模块拆分比拟多,迁徙到微服务比方用 springcloude 或者 dubbo 的时候十分好用。
  2. 依照业务模块拆分,这种模式应用的比拟多,也比拟多见。

创立一个多 module 我的项目(idea2019.3.3 版本)

创立一个父 pom 我的项目:

  1. 关上 idea,抉择create new project

  1. 抉择 maven 我的项目,同时不选任何的预加载设置

  1. 父 pom 配置如下:

  1. 删除src 目录

创立子模块,引入到父 pom 外面

  1. 同样右击我的项目工程,抉择new module,而后抉择maven,这时候会呈现父模块以及对应的子模块名称

  1. 此时在父模块外面发现引入了子模块的内容

子父模块的区别:

父 pom.xml 文件内容:

<groupId>org.zxd</groupId>
<artifactId>taglib</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>

<modules>
    <module>taglib-core</module>
</modules>

分为两个局部,一个局部是父 pom 的申明,蕴含 gourpId,artifactId,打包形式 必须是 pom,因为应用了 聚合模型,同时在父 pom 外面指定版本号,子模块不填写 version 会默认应用父 pom 的 version 号

<modules>
    <module>taglib-core</module>
</modules>

下面示意以后引入的子模块内容

子 pom.xml 文件内容:

<!-- 援用自父 pom -->
<parent>
    <artifactId>taglib</artifactId>
    <groupId>org.zxd</groupId>
    <version>1.0.0</version>
</parent>
<!-- 打包形式为 jar 包 -->
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>

<artifactId>taglib-core</artifactId>
<version>1.0.0</version>

子模块之间进行相互的依赖

在上面的 pom 中能够在任意的子模块引入对应的父模块依赖

留神因为 <parent> 这个标签会递归继承,所以要留神子依赖不要和依赖引入不同版本的依赖,这样容易造成抵触

<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <!-- 这里须要正文掉编译的作用域 -->
    <!--<scope>compile</scope>-->
</dependency>

将下面的我的项目革新为 spring-boot 多模块我的项目:

革新父 pom 文件:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

parent 指向springboot-started

子模块只须要引入父 pom 的内容

Spring boot maven plugin 问题

在打包 spring boot 我的项目时,须要应用如下插件:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

如果在用 maven 构建多模块我的项目时,不要将此插件放到 parent pom 中,否则如果有 sub module 不是 spring boot 利用,在打包时就会出错。只将该插件增加到是 spring boot 我的项目的子模块

MAVEN 依赖抵触问题:

依赖的传递准则:

  1. 最短门路准则
  2. 最先申明准则

maven 的依赖引入策略

最短门路准则:

我有上面两个依赖 jar 包,A 和 B,他们都引入了 C 这个依赖,这时候如果有如下的援用

A -> C(3.3)

B -> A(3.3)

B -> C(3.4)

此时如果把 B 打包,失去版本号是 3.4,然而如果 B 去掉 C 的依赖,那就是走 A ->C 的传递依赖,很简略

验证:

  1. 我假如我有一个 web 包引入了 common-lang3,版本是 3.4 的版本
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>
  1. 此时又引入了一个专用包,外面也有这个援用:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.3</version>
</dependency>
  1. 如果此时在本地援用 3.4 版本,那就是 3.4 的版本,否则就死 3.3 的版本,不论申明程序谁先谁后

最先申明准则:

如果两个 jar 包的寻址门路统一,那么谁先优先申明,先引入谁

验证:

上面两个依赖调配对应两个 module,引入模块的这个模块暂定为 C 模块。

<!-- 引入 core 包内容 -->
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-core</artifactId>
    <version>1.0.0</version>
    <!--            <scope>compile</scope>-->
</dependency>
<!-- 引入 db 包的内容 -->
<dependency>
    <groupId>org.zxd</groupId>
    <artifactId>taglib-db</artifactId>
    <version>1.0.0</version>
</dependency>

此时 taglib-core 中的依赖版本如下,暂定为 A 模块:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>2.5.0</version>
</dependency>

taglib-db 中的依赖版本如下,暂定为 B 模块:

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
    <version>4.0.1</version>
</dependency>

此时将整个 web 我的项目打包,能够看到 web 我的项目外面的版本如下:

能够很显著的看到如果引入关系是这样的:

C -> A,B

A -> curator-client 2.5

B -> curator-client 4.1

这样的链路最终打包进去的成果是 C -> A -> curator-client 2.5

这样也就造成了很多状况下咱们 编译 运行 时齐全没有问题的,甚至有可能打包都是失常 的,然而到最初运行的时候忽然报错,要谨防这种依赖版本的问题,好在个别公司的我的项目都有经理负责管制版本依赖,这种谬误算是低级谬误,然而在现在框架满天飞的时代,依赖治理的版本控制问题仍然须要留神!!!

如何解决依赖抵触的问题

锁定版本法

个别状况下咱们会在父 pom 文件外面治理,能够应用 <dependencyManagement> 这个这个标签来治理所有子模块的版本依赖,子模块如果指定本人的版本,这里发现打进去的包仍然是父 pom 指定的版本,版本治理应用如下:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-client</artifactId>
            <version>4.1.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

锁定版本法能够突破 2 个依赖传递的准则,优先级为最高

版本锁定能够排除一些 exclude 标签,不同模块用不同版本的 jar 包自身也不符合规范,所以这种形式较为稳当

什么状况下会呈现 Jar 包抵触问题

只有高版本 Jar 包不向下兼容,或者新增了某些低版本没有的 API 才有可能导致这样的问题

如何查找和发现 jar 包抵触?

1. 利用 idea 的 maven 视图工具

间接应用一个图阐明一下:

能够通过这个工具查看依赖在哪个模块反复援用,同时如果有抵触会显示红线,这个视图十分的直观,能够帮忙依赖管理人员去解决依赖反复援用或者援用版本不统一的问题,进行 <exclude> 操作

2. Idea Maven Helper 插件

如何应用?

装置实现之后,轻易找一个 pom.xml 文件,依照如下的图例提醒进行操作,对于抵触的内容,右击 exclude 就能够排除依赖:

排除完依赖之后,点击左上角的Refresh UI 刷新一下 UI 的界面:

3. maven 命令工具:

mvn dependency:tree -Dverbose,有时候如果咱们没有 idea 的状况下,能够应用这个命令来解决,执行的后果参考如下:

PS: 此处肯定不要省略 -Dverbose 参数,要不然是 不会 显示被 疏忽 的包的

or:curator-client:jar:4.1.0:compile
[INFO] |  |  +- org.apache.zookeeper:zookeeper:jar:3.5.4-beta:compile
[INFO] |  |  |  +- commons-cli:commons-cli:jar:1.2:compile
[INFO] |  |  |  +- log4j:log4j:jar:1.2.17:compile
[INFO] |  |  |  +- org.apache.yetus:audience-annotations:jar:0.5.0:compile
[INFO] |  |  |  \- io.netty:netty:jar:3.10.6.Final:compile
[INFO] |  |  +- com.google.guava:guava:jar:20.0:compile
[INFO] |  |  \- org.slf4j:slf4j-api:jar:1.7.30:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.15:compile
[INFO] |  +- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] |  +- commons-beanutils:commons-beanutils:jar:1.9.4:compile
[INFO] |  +- commons-configuration:commons-configuration:jar:1.10:compile
[INFO] |  |  \- commons-lang:commons-lang:jar:2.6:compile

总体上来说还是比拟直观的,十分不便和好用。

如何写一个洁净依赖关系的 POM 文件

  • 尽量在父 POM 中定义<dependencyManagement>,来进行本我的项目一些依赖版本的治理,这样能够从很大水平上解决肯定的抵触
  • 起码依赖 jar 包准则
  • 应用 mvn dependency:analyze-only 命令用于检测那些申明了然而没被应用的依赖,如有有一些是你本人申明的,那尽量去掉
  • 应用 mvn dependency:analyze-duplicate 命令用来剖析反复定义的依赖,清理那些反复定义的依赖

dependency:analyze-only 命令

在 idea – Terminal外面,能够看到对应的依赖被下载

执行完之后我的运行后果如下,这里报错的起因是打包时候默认去阿里云仓库寻找依赖,这里须要配置一下:

[ERROR] Failed to execute goal on project taglib-web: Could not resolve dependencies for project org.zxd:taglib-web:war:1.0.0: The following artifacts could not be resolved: org.zxd:
taglib-core:jar:1.0.0, org.zxd:taglib-db:jar:1.0.0: Failure to find org.zxd:taglib-core:jar:1.0.0 in http://maven.aliyun.com/nexus/content/repositories/central/ was cached in the loc
al repository, resolution will not be reattempted until the update interval of alimaven has elapsed or updates are forced -> [Help 1]

大抵意思就是说再阿里云仓库找不到对应的依赖引入。

解决形式如下:

找到 maven 的装置门路下的 apache-maven-3.6.3\conf 上面的setting.xml,找到如下配置:

<!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
<!-- 这里配置本地仓库的地位 -->
  <localRepository>D:\soft\apache-maven-3.6.3\rep</localRepository>

此时从新执行一下:dependency:analyze-only 命令

[INFO] --- maven-dependency-plugin:3.1.2:analyze-only (default-cli) @ taglib-web ---
[WARNING] Unused declared dependencies found:
[WARNING]    org.zxd:taglib-core:jar:1.0.0:compile
[WARNING]    org.apache.commons:commons-lang3:jar:3.4:compile
[WARNING]    org.springframework.boot:spring-boot-starter-web:jar:2.4.0:compile
[WARNING]    org.springframework.boot:spring-boot-starter-test:jar:2.4.0:test
[WARNING]    org.neo4j.driver:neo4j-java-driver:jar:1.5.0:compile
[WARNING]    commons-codec:commons-codec:jar:1.10:compile
[WARNING]    commons-collections:commons-collections:jar:3.2.2:compile
[WARNING]    commons-beanutils:commons-beanutils:jar:1.9.4:compile
[WARNING]    commons-configuration:commons-configuration:jar:1.10:compile
[WARNING]    commons-fileupload:commons-fileupload:jar:1.3:compile
[WARNING]    commons-logging:commons-logging:jar:1.2:compile
[WARNING]    org.apache.httpcomponents:httpclient:jar:4.4.1:compile
[WARNING]    org.apache.poi:poi-ooxml:jar:3.17:compile
[WARNING]    org.mybatis:mybatis:jar:3.4.0:compile
[WARNING]    org.mybatis:mybatis-spring:jar:1.3.0:compile
[WARNING]    com.github.pagehelper:pagehelper:jar:5.1.2:compile

mvn dependency:analyze-duplicate 命令

[INFO] No duplicate dependencies found in <dependencies/> or in <dependencyManagement/>

如果没有其余信息,代表没有反复依赖的引入

退出移动版