Maven:分模块设计、继承、版本锁定与聚合

 💥 该系列属于【SpringBoot基础】专栏,如您需查看其他SpringBoot相关文章,请您点击左边的连接

目录

一、分模块设计介绍

二、项目准备

三、模块拆分实践

1. 创建Maven模块tlias-pojo

2. 创建Maven模块tlias-utils

四、继承

1. 为什么需要继承

2. 继承的实现

五、版本锁定

1. 为什么要版本锁定

2. 版本锁定的实现

3. 自定义属性

六、聚合

1. 什么是聚合

2. 聚合的实现

3. 继承和聚合


一、分模块设计介绍

所谓分模块设计就是我们在设计一个 Java 项目的时候,将一个 Java 项目拆分成多个模块进行开发。

如果项目不分模块,随着这个项目的业务扩张,项目当中的业务功能可能会越来越多。假如开发的是一个大型的电商网站,这个项目组至少几十号甚至几百号开发人员,这些开发人员全部操作这一个 Java 项目。此时,主要有两点问题:不方便项目的维护和管理、项目中的通用组件难以复用。

分模块设计我们在进行项目设计阶段,就可以将一个大的项目拆分成若干个模块,每一个模块都是独立的。

二、项目准备

提前准备一个单模块的springboot项目,将它拆分成多个模块,项目结构如下:

像pojo和utils这样的文件,里面通常存放了一些公共组件,可以进行如下拆分:

  • 将pojo包下的实体类,抽取到一个maven模块中 tlias-pojo

  • 将utils包下的工具类,抽取到一个maven模块中 tlias-utils

  • 其他的业务代码,放在tlias-web-management这个模块中,在该模块中需要用到实体类pojo、工具类utils,直接引入对应的依赖即可。

 也即:

三、模块拆分实践

1. 创建Maven模块tlias-pojo

点击【新建】,选择【模块】,然后新建一个Maven项目:

此时的项目结构:

下一步,将tlias-web-management里面的pojo复制到tlias-pojo:

此时发现报了一堆错,原因是没有引入相关的依赖。因此,需要手动引入依赖防止报错:

引入lombok依赖后不再报错。

然后删除tlias-web-management里面的pojo:

删除后可以发现tlias-web-management的其他文件报错了,原因是不再能找到pojo里面的实体类:

 因此需要在tlias-web-management引入tlias-pojo依赖,引入后不再报错:

2. 创建Maven模块tlias-utils

同理,创建tlias-utils,省略以上步骤,创建结果如下:

四、继承

1. 为什么需要继承

在上面的tlias-pojo、tlias-utils、tlias-web-management中都引入了一个依赖 lombok 的依赖。我们在三个模块中分别配置了一次。

如果是做一个大型的项目,这三个模块当中重复的依赖可能会很多很多。如果每一个 Maven 模块里面,我们都来单独的配置一次,功能虽然能实现,但是配置是比较繁琐的。

我们可以再创建一个父工程 tlias-parent ,然后让上述的三个模块 tlias-pojo、tlias-utils、tlias-web-management 都来继承这个父工程 。 然后再将各个模块中都共有的依赖,都提取到父工程 tlias-parent中进行配置,只要子工程继承了父工程,依赖它也会继承下来,这样就无需在各个子工程中进行配置了。

当前的项目tlias-web-management是一个springboot项目,而所有的springboot项目都有一个统一的父工程,就是spring-boot-starter-parent。Maven不支持多继承,但是可以支持多重继承,可以让三个模块都继承 tlias-parent ,而 tlias-parent 再继承 spring-boot-starter-parent 。 具体结构如下:

2. 继承的实现

(1)创建Maven模块tlias-parent

下一步,设置pom打包方式,在tlias-parent中引入springboot的父工程,并删除src文件

(2)子工程配置继承关系

下一步,在tlias-web-management子工程的pom.xml文件中指定父工程为tlias-parent(并删除原来的springboot父工程),并删除groupId

注意事项

  • 在子工程中,配置了继承关系之后,坐标中的groupId可省略,会自动继承父工程。
  • relativePath指定父工程的pom文件的相对位置(如果不指定,将从本地仓库/远程仓库查找该工程)。

同理,在tlias-utils和tlias-pojo的子工程中也要指定

(3)父工程配置共有依赖

共有依赖只有lombok,因此将lombok依赖放在父工程中,并删除所有子工程配置的lombok依赖即可,然后刷新maven。

结果,在所有子工程中都有lombok依赖: 

(4)工程结构说明

我们当前的项目结构为:

因为是项目开发完毕之后,基于现有项目拆分的各个模块,tlias-web-management已经存在了,然后再创建各个模块与父工程,所以父工程与模块之间是平级的。

而实际项目中,可能是下面的工程结构:

而在真实的企业开发中,都是先设计好模块之后,再开始创建模块,开发项目。此时一般都会先创建父工程 tlias-parent,然后将创建的各个子模块,都放在父工程parent下面。 这样层级结构会更加清晰一些。

PS:上面两种工程结构都可以正常使用,只不过第二种父子工程结构更加清晰和直观。

五、版本锁定

1. 为什么要版本锁定

考虑下面这样的场景,有三个模块使用了jjwt:0.9.1模块,现在要统一更新成0.9.2的版本,如果要在每个模块中逐一更新,那么会非常繁琐

如何来统一管理各个依赖的版本呢?可以使用Maven的版本锁定功能

 在maven中,可以在父工程的pom文件中通过 <dependencyManagement> 来统一管理依赖版本,子工程引入依赖无须指定<version>版本号。

问:<dependencyManagement>与<dependencies>的区别是什么?

  • <dependencies> 是直接依赖,在父工程配置了依赖,子工程会直接继承下来。
  • <dependencyManagement> 是统一管理依赖版本,不会直接依赖,还需要在子工程中引入所需依赖(无需指定版本)

2. 版本锁定的实现

运行结果:

PS:在springboot项目中很多时候,引入依赖坐标都不需要指定依赖的版本 <version> ,是因为在父工程 spring-boot-starter-parent中已经通过 <dependencyManagement>对依赖的版本进行了统一的管理维护。

3. 自定义属性

我们也可以通过自定义属性及属性引用的形式,在父工程中将依赖的版本号进行集中管理维护。 具体语法为:

1). 自定义属性

<properties>
    <lombok.version>1.18.24</lombok.version>
</properties>

2). 引用属性

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>${lombok.version}</version>
</dependency>

完整的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.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.itheima</groupId>
    <artifactId>tlias-parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>


    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>

        <lombok.version>1.18.30</lombok.version>
        <jjwt.version>0.9.1</jjwt.version>
        <aliyun.oss.version>3.15.1</aliyun.oss.version>
        <jaxb.version>2.3.1</jaxb.version>
        <activation.version>1.1.1</activation.version>
        <jaxb.runtime.version>2.3.3</jaxb.runtime.version>
    </properties>


    <!-- 子工程共有的依赖 -->
    <dependencies>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
    </dependencies>

    <!-- 统一管理依赖版本,而不会引入依赖 -->
    <dependencyManagement>

        <dependencies>
            <!--阿里云OSS-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun.oss.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>${jaxb.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>${activation.version}</version>
            </dependency>
            <!-- no more than 2.3.3-->
            <dependency>
                <groupId>org.glassfish.jaxb</groupId>
                <artifactId>jaxb-runtime</artifactId>
                <version>${jaxb.runtime.version}</version>
            </dependency>

            <!--JWT令牌-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jjwt.version}</version>
            </dependency>
        </dependencies>

    </dependencyManagement>

</project>

六、聚合

当前的案例项目,结构如下(相对还是比较简单的):

此时,tlias-web-management 模块的父工程是 tlias-parent,该模块又依赖了tlias-pojo、tlias-utils模块。 如果想将 tlias-web-management 模块打包,是比较繁琐的。因为在进行项目打包时,maven会从本地仓库中来查找tlias-parent父工程,以及它所依赖的模块tlias-pojo、tlias-utils,而本地仓库目前是没有这几个依赖的。

所以,我们再打包tlias-web-management 模块前,需要将 tlias-parent、tlias-pojo、tlias-utils分别执行install生命周期安装到maven的本地仓库,然后再针对于 tlias-web-management 模块执行package进行打包操作。

如果开发一个大型项目,拆分的模块很多,模块之间的依赖关系错综复杂,那此时要进行项目的打包、安装操作,是非常繁琐的。因此maven的聚合就是来解决这个问题的,通过maven的聚合就可以轻松实现项目的一键构建(清理、编译、测试、打包、安装等)。

1. 什么是聚合

  • 聚合:将多个模块组织成一个整体,同时进行项目的构建。

  • 聚合工程:一个不具有业务功能的空工程(有且仅有一个pom文件) ,一般来说,继承关系中的父工程与聚合关系中的聚合工程是同一个

  • 作用:快速构建项目(无需根据依赖关系手动构建,直接在聚合工程上构建即可)

2. 聚合的实现

在maven中,我们可以在聚合工程中通过 <moudules> 设置当前聚合工程所包含的子模块的名称。我们可以在 tlias-parent 中,添加如下配置,来指定当前聚合工程,需要聚合的模块:

<!--聚合其他模块-->
<modules>
    <module>../tlias-pojo</module>
    <module>../tlias-utils</module>
    <module>../tlias-web-management</module>
</modules>

那此时,我们要进行编译、打包、安装操作,就无需在每一个模块上操作了。只需要在聚合工程上,统一进行操作就可以了。

3. 继承和聚合

(1)作用

  • 聚合用于快速构建项目
  • 继承用于简化依赖配置、统一管理依赖

(2)相同点

  • 聚合与继承的pom.xml文件打包方式均为pom,可以将两种关系制作到同一个pom文件中
  • 聚合与继承均属于设计型模块,并无实际的模块内容

(3)不同点

  • 聚合是在聚合工程中配置关系,聚合可以感知到参与聚合的模块有哪些
  • 继承是在子模块中配置关系,父模块无法感知哪些子模块继承了自己

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值