Maven项目之间关系介绍

Maven项目之间的关系

依赖关系

单纯的项目A中需要项目B中的资源,将项目B打成Jar包被A依赖,此时项目A直接调用项目B中资源即可。

项目A和项目B此时形成最基本的依赖关系。

继承关系

需要场景:
如果多个子项目中使用的是相同的依赖或插件,此时我们可以把相同的配置抽取到一个父项目中,进行统一的管理,保持一致性。所以继承关系此时显得比较重要,在java中,继承体现在代码功能上,而maven中的继承则体现在pom.xml,跟功能代码没有关系,当项目A继承了项目B,则项目A拥有了项目B的pom.xml文件中所有依赖。当然继承中也不同的用法和不同的场景。

我们在同级目录创建01_parent、02_child、03_child,一个父项目,两个子项目

01_parent的pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 将其作为maven项目的父项目,统一管理子项目的公共依赖 -->
  <groupId>org.example</groupId>
  <artifactId>01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 父项目的专有打包方式,该种方式,本项目不会被打包成 jar 或 war ,项目里 src 目录下代码无效(可删除), pom.xml 有效,只是作为其它项目的父项目使用. -->
  <packaging>pom</packaging>
  <properties>
      <spring-version>5.2.9.RELEASE</spring-version>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <!--配置webmvc-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <dependency>
          <groupId>log4j</groupId>
          <artifactId>log4j</artifactId>
          <version>1.2.17</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
  </dependencies>
</project>

02_child的pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

<!-- <groupId>org.example</groupId> 如果子项目和父项目在同一级目录,使用parent标签表明了父项目坐标后,子项目的groupId可以省去 -->
    <artifactId>02_child</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

03_child的pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>03_child</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

然后我们看看maven项目之间的关系:

20210915102806

我们很明显的看到,两个子项目都成功的拥有了父项目的依赖。maven的基本继承关系就弄完了。

但是实际开发中,我们可能有多个功能不同得子项目,父项目中的依赖并不是每一个子项目都必须全部需要的。这个时候如果子项目拥有了父项目全部依赖就有点说不过去了,甚至可能产生jar包冲突。

这里我们可以使用<dependencyManagement>标签来解决我们上述的问题,这个标签的作用其实相当于一个对所依赖 jar 包进行版本管理的管理器.( dependencyManagement 里只是声明依赖,并不实现引入)

这样一来,父项目就像超市,子项目就像客户,父项目将部分不是基本的依赖放入其中,子项目需要就声明即可,不需要的话父项目也不会强人所难。

01_parent的pom.xml:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!-- 将其作为maven项目的父项目,统一管理子项目的公共依赖 -->
  <groupId>org.example</groupId>
  <artifactId>01_parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <!-- 父项目的专有打包方式,该种方式,本项目不会被打包成 jar 或 war ,项目里 src 目录下代码无效(可删除), pom.xml 有效,只是作为其它项目的父项目使用. -->
  <packaging>pom</packaging>
  <properties>
      <spring-version>5.2.9.RELEASE</spring-version>
  </properties>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <!--配置webmvc-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring-version}</version>
      </dependency>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
  </dependencies>

  <!--dependencyManagement 标签中声明的依赖,只是作为一个 jar 包统一管理的管理器,实际上该标签中声明的依赖不会被引入-->
  <dependencyManagement>
      <dependencies>
          <dependency>
              <groupId>log4j</groupId>
              <artifactId>log4j</artifactId>
              <version>1.2.17</version>
          </dependency>

          <dependency>
              <groupId>commons-logging</groupId>
              <artifactId>commons-logging</artifactId>
              <version>1.0</version>
          </dependency>
      </dependencies>
  </dependencyManagement>
</project>

在01_parent这个“超市”中添加了log4j和commons-logging的两个依赖供子项目选择。

此时02_child需要log4j这个依赖:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

<!-- <groupId>org.example</groupId> 如果子项目和父项目在同一级目录,使用parent标签表明了父项目坐标后,子项目的groupId可以省去 -->
    <artifactId>02_child</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </dependency>
    </dependencies>
</project>

03_child需要commons-logging这个依赖:

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.example</groupId>
        <artifactId>01_parent</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>03_child</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
        </dependency>
    </dependencies>
</project>

看maven项目之间的依赖:

20210915104321

此时02_child没有了commons-logging,03_child没有了log4j,我们已经解决了这个问题。

如果子项目使用的依赖不是父项目的版本,需要在子项目的pom中标明依赖的版本,否则默认使用的是父项目管理的版本。

其实我们这个问题主要是学习<dependencyManagement>这一标签在父项目中的作用

打包

此时我们对02_child进行打包会报错,具体原因是:

Non-resolvable parent POM for org.example:02_child:1.0-SNAPSHOT: Could not find artifact org.example:01_parent:pom:1.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13@

说子项目解析不了父项目的POM文件,parent.relativePath错误。其实,我们在子类的parent标签中还要加一个<relativePath>标签,来指明父项目中POM的相对物理路径,这样子项目打包的时候,maven才能工具标签找到父项目的POM地址,不然也不知道子项目的引用从哪来。

项目报错:

  • 子项目打包出错:Invalid packaging for parent POM com.cloud:DemoName:1.0-SNAPSHOT, must be “pom“ but is “jar“。

    我们必须在父项目中pom指定打包格式为POM:<packaging>pom</packaging>

  • Could not find artifact com.cloud:DemoName:pom:1.0-SNAPSHOT

    子项目打包前必须先打包父项目

聚合关系

聚合本身没有实质的内容,随着程序的发展,项目也会越来越大,功能越来越多,开发人员往往会将其划分模块进行开发,功能清晰,设计清晰。maven的聚合特性就是将多个模块聚合在一起构建。并且聚合是建立在继承关系上,父项目的作用除了统一管理子项目的依赖,还做最后统一构建所有子模块,实现一次构建多个项目!

此处做个比喻,有一天我们被要求制作一个“强大”的机器,机器人靠着很多零件组装,团队有4个人,一个管理员,三个开发人员,管理员将其工具包分成三个局部零件交给我们开发,我们每人一个不同的零件开发模块,并在管理员下进行开发。我们开发时,如果零件模块之间没有互相依赖的关系可以并行开发,如果有单向依赖关系那就得看具体需求了。

当我们开发完成后统一交给管理员对我们的局部零件进行组装,最后的结果就是管理员(Maven)统一聚合项目下所有子模块成为最终项目成果。

代码就不演示了,我使用的是MVC分成4个模块(pojo,mapper,serivce,controller),单项依赖感觉不能讲的很清楚,其实自己对聚合关系也只是一知半解,了解基本,还没有进行实质的开发。体会不到聚合关系带来的便利(才学疏浅),要了解详情就要去看别的博客了。

小结

本次是对Maven项目之间三大关系的介绍:

  • 最基本的依赖关系:A依赖B
  • 继承关系:B和C的公共依赖、部分依赖被A统一管理
  • 聚合关系:B、C功能模块开发完,被A统一进行聚合成完整的功能或项目。(聚合关系建立在继承关系上)
posted @ 2021-09-18 09:43  CN_DADA  阅读(435)  评论(0编辑  收藏  举报