Java--Maven多模块管理

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--Maven多模块管理相关的知识,希望对你有一定的参考价值。

我们开发一个很大的项目工程时,会用到很多模块或者子工程进行同步开发,如

CommonModel:公共的基础服务,比如工具类、常量类等等;

BussinessModel:业务模块,是系统真正要实现的业务,依赖于 common 模块,比如菜单管理、订单管理、权限管理、角色管理等;

Application:可发布的 web 应用,由各个 BussinessModel 组成,最终满足项目整体需求;

第三方模块(Library):包括各类框架,Spring、Springboot、SpringCloud等

Maven 管理多模块应用的实现是互联网项目中多使用分布式开发,每个独立的服 务都会使用独立的项目进行维护,那么这样就需要使用多模块应用管理,来实现项目的高度统一

Maven进行多模块工程管理主要有如下三种方式

一、创建空工程Empty Project,设置Parent父工程

1、创建一个空工程Empty Project

(1)File----New----Project,选择Empty Project,点击Next

(2)输入工程名,以及存放路径

Project name:项目名称

Project location:项目存放位置路径

2、创建Maven父工程

(1)File----New----Module

(2)选择Maven工程,是否选择模板创建,如果只是普通Java项目可直接下一步,不用勾选

maven-archetype-quickstart : 普通java项目(可选可不选,不选默认是普通Java工程)

(3)输入父工程,模块名,模块存放位置,以及模块坐标(gav)信息

Parent:父工程名(如果创建的工程本身就是父工程,这里选择None)

Name:子工程/模块名

Location:子工程/模块存放位置路径

GroupId:公司域名的倒序

ArtifactId:项目或模块名称

Version:项目或模块版本号

(4)配置导入设置

Maven 项目被修改后,需要“手动更新”或“自动更新”,通常选择右下角弹出框的

“Enable Auto-Import”

maven父工程必须遵循两点要求:

1、packaging标签的文本内容必须设置为pom

2、将src目录删除掉

(5)设置父工程的 pom.xml 文件

maven父工程必须遵循两点要求:

1、packaging标签的文本内容必须设置为pom

2、将src目录删除掉

此时可以看到 pom.xml 文件中内容如下

<modelVersion>4.0.0</modelVersion>

    <groupId>com.mycompay</groupId>
    <artifactId>maven-modules-1-parent</artifactId>
    <version>1.0.0</version>

    <!--
        maven父工程必须遵循两点要求:
            1、packaging标签的文本内容必须设置为pom
            2、将src目录删除掉
    -->
    <packaging>pom</packaging>

(6)删除 src 文件目录

如果有子工程\\模块,会看到左上角有一个 m↓ 标记,点击选择可以跳转的子模块/工程

3、创建Maven子模块

(1)File----New----Module

(2)选择Maven工程,是否选择模板创建,如果只是普通Java项目可直接下一步,不用勾选

如果是web子模块,勾选如下

(3)选择父工程模块

Add as module to:选择将创建的模块添加到哪个模块下(老版本IDEA中有)

Parent:选择模块的父工程

GroupId:选择父工程后,默认继承父工程的 GroupId 值

ArtifactId:模块的项目名称

Version:选择父工程后,默认继承父工程的 Version 值

如果我们直接选择父工程,右键 “File----New----Module”,则这里会 parent 自动带出父工程名称

如果是2019版本IDEA,会有 Add as module to 这个选项,在这里选择None

博主当前使用的2021版本IDEA,因此没有 Add as module to 这个选项

在parent选择父工程之后,GroupId和Version会自动带出

如下是2021版IDEA

如下是2019版IDEA 

 web子模块同理

(4)模块目录视图

 我们发现子模块的 pom.xml 文件左上角有一个 m↑ 这个标记,点击可跳转到父工程的 pom.xml 文件中

web子模块视图,packing标签多了一个 war

 (5)子模块的 pom.xml 文件

parent 标签:指向父工程

relativePath 标签:相对路径(父工程的 pom.xml 文件相对路径)

除了子模块名可以修改,其他公司域名,version等都是继承父工程

    <!--指向父工程的GAV坐标-->
    <parent>
        <artifactId>maven-modules-1-parent</artifactId>
        <groupId>com.mycompany</groupId>
        <version>1.0.0</version>
        <relativePath>../maven-modules-1-parent/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-modules-1-java</artifactId>

4、创建子模块的下级子模块

按照上述创建子模块方式,选择父模块为上一级子模块即可

 我们可看下创建后的视图

二、创建Maven父工程,设置 Add as module to Parent

1、创建Maven父工程

(1)File----New----Project

(2)选择Maven工程,是否选择模板创建,如果只是普通Java项目可直接下一步,不用勾选(这里不用勾选,Java和web工程都无所谓)

(3)设置父工程项目名称和项目存放位置;并填写坐标(gav)信息

(4)配置导入设置

Maven 项目被修改后,需要“手动更新”或“自动更新”,通常选择右下角弹出框的

“Enable Auto-Import”

(5)将本maven工程修改为父工程

【1】设置 pom.xml 文件的 packing标签为  pom

【2】删除 src 目录

如果父工程下有子模块,在父工程的 pom.xml 文件

 会有 <modules> 标签,如上,点击左上角的 m↓ 标记,可跳转到指定子模块工程

2、创建Maven子模块/工程 

(1)File----New----Module

(2)选择Maven工程,Java工程可直接下一步

(3)选择父工程

Add as module to:选择将创建的模块添加到哪个模块下(老版本IDEA中有)

Parent:选择模块的父工程

GroupId:选择父工程后,默认继承父工程的 GroupId 值

ArtifactId:模块的项目名称

Version:选择父工程后,默认继承父工程的 Version 值

如果我们直接选择父工程,右键 “File----New----Module”,则这里会 parent 自动带出父工程名称

注:

如果是2019版本IDEA,会有 Add as module to 这个选项,在这里选择父工程,和 Parent 选项的父工程保持一致

博主当前使用的2021版本IDEA,因此没有 Add as module to 这个选项

在parent选择父工程之后,GroupId和Version会自动带出

如下是2021版IDEA

 如下是2019版IDEA

(4)创建之后视图

子模块就在父工程目录之下了

 同理,再创建一个web工程

 

 此时,工程目录如下

我们再去看一下父工程的 pom.xml 文件

 此时会多一个 <modules> 标签,如上,点击左上角的 m↓ 标记,可跳转到指定子模块工程

同理,我们也可以按照上述方式给子模块在创建子模块下的子模块(第三层,第四层......第N层等)

三、上述两种方式混合使用

如我们可以以第一种方式创建多个Maven父工程,再以第二种方式在每个父工程下创建子工程混合使用

四、设置父工程编译级别

Maven项目中会统一使用 JDK 版本和编译级别,将编 译插件添加到父工程,子模块依然会无条件去继承父工程的插件

1、查看编译级别

File ----> Settings ----> Build, Execution, Deployment ----> Compiler ----> Java Compiler

2、在父工程中的 pom.xml 文件 build ----> plugins 标签中添加编译插件

    <build>
        <plugins>
            <!--JDK1.8编译插件-->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- 插件的版本 -->
                <version>3.1</version>
                <!-- 编译级别 -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <!-- 编码格式 -->
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

如下

修改完成之后,我们点击右边工具栏的中的 Maven,点击 “刷新”按钮即可

 此时再去查看,都变为 1.8版本了

五、管理依赖

Maven多模块管理的实质实现依赖的版本统一管理

如果每个子模块都有自己依赖的jar包,且版本不同,那么在工程代码合并时会造成很大冲突,如子模块1 使用 mysql 5.1版本,而子模块2 使用 mysql 8.0版本,势必造成版本不统一,且有些参数,函数方法等会找不到等问题,那么合项目也是很大的困难

如下,我们在子模块maven-modules-1-java的 pom.xml文件 有Junit和 mysql5.1.49 依赖,刷新

在子模块 maven-modules-1-web的 pom.xml文件  有mysql8.0.19 依赖,刷新

这样就导致了两个子模块的 mysql 依赖版本不同,势必会出错

那么我们将子模块下的 pom.xml 文件里面的所有依赖都添加到  父工程下,删掉子模块下的 依赖<dependencies>  和 <dependency>标签

此时发现所有工程/模块(包括父工程,所有子模块)都有父工程 pom.xml 文件中添加的所有依赖jar包,如下

以上写做法,子模块会无条件继承父工程的所有依赖,导致的问题是,造成依赖 jar 包的 冗余 和 空间的浪费,本不需要的继承 的依赖也会被继承,这就大大增加了项目模块最终打包的大小,也可能未上线埋下了隐患。

父工程管理的是所有项目模块的依赖,而不是某一个项目模块的依赖,所以 某一个项目模块不需要继承父工程中的所有依赖,这就需要子项目模块向父工程声明需要的 依赖即可(声明式依赖

此时,父工程实际只需要管理依赖的版本号即可

最终版本

1、在父工程添加依赖管理,使用 <dependencyManagement> 标签管理

子模块项目之前继承的依赖消失,由于父工程通过 dependencyManagement 标签管理依 赖,那么之前子模块无条件继承的依赖就全部消失

2、自定义标签名称
在 Maven 的 pom.xml 文件中,<properties>用于定义全局变量
POM 中通过$property_name的形式引用变量的值,标签名称一般由 项目名称 + 字段version组成
单个单词可直接 XX.version命名,多个单词可横线分割 XX-XX-version

父工程 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>

    <groupId>com.mycompany</groupId>
    <artifactId>maven-modules-1-parent</artifactId>
    <version>1.0.0</version>

    <!--
        maven父工程必须遵循两点要求:
            1、packaging标签的文本内容必须设置为pom
            2、将src目录删除掉
    -->
    <packaging>pom</packaging>

    <!--
        packaging标签的是指定打包的方式
        默认为jar,如果pom文件中没有packaging标签那么默认就是打jar
    -->

    <!--
        pom是项目对象模型(Project Object Module),该文件是可以被子工程继承
        maven多模块管理 其实就是让它的子模块的pom文件来继承父工程的pom文件
    -->

    <!-- 父管理依赖的版本号 -->
    <properties>
        <!--
          自定义标签名称
          在 Maven 的 pom.xml 文件中,<properties>用于定义全局变量
          POM 中通过$property_name的形式引用变量的值,标签名称一般由 项目名称 + 字段version组成
          单个单词可直接 XX.version命名,多个单词可横线分割 XX-XX-version
        -->
        <junit.version>4.10</junit.version>
        <mysql-connector-java-version>8.0.19</mysql-connector-java-version>
        <dubbo.version>2.6.2</dubbo.version>
        <spring-webmvc-version>4.3.16.RELEASE</spring-webmvc-version>
    </properties>

    <!--父工程要加强管理子模块的所有依赖-->
    <dependencyManagement>
        <!--父工程添加的依赖,所有子模块会无条件的继承-->
        <dependencies>
            <!-- junt依赖 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>$junit.version</version>
            </dependency>

            <!--mysql依赖 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>$mysql-connector-java-version</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <!--JDK1.8编译插件-->
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- 插件的版本 -->
                <version>3.1</version>
                <!-- 编译级别 -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <!-- 编码格式 -->
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3、子模块声明式添加依赖

由于父工程管理依赖的版本号,那么子模块要想继承依赖,只能通过声明式来添加依赖

实际上,子模块中的依赖是继承父工程依赖的版本号

如果子模块已定义依赖版本号,那么 以子模块定义的版本号为准

子工程 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">
    <parent>
        <artifactId>maven-modules-1-parent</artifactId>
        <groupId>com.mycompany</groupId>
        <version>1.0.0</version>
        <relativePath>../maven-modules-1-parent/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>maven-modules-1-java</artifactId>

    <!-- 设置packing为pom -->
    <packaging>pom</packaging>

    <!--
        子模块可实现自己的依赖,但是默认不带版本号version,继承父类工程依赖版本号;
        也可以修改自己的依赖版本号
     -->
    <dependencies>
        <!-- 声明式依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

</project>

这时我们查看右方工具栏中的 Maven,可看到其他没写依赖的子模块,不会有依赖,只有声明要继承依赖的子模块才会有

以上是关于Java--Maven多模块管理的主要内容,如果未能解决你的问题,请参考以下文章

推荐学Java——Maven初识

Java Maven打包总结(Jenkins多模块编译部署)

多模块 Java/Maven 项目中 DBUnit 的 XML DTD 路径?

推荐学Java——Maven初识

什么是目前比较常用的Python扩展库管理工具

Maven管理多模块