一、什么是多模块项目
多模块项目是项目构建中的概念。拿 Maven 来说,多模块项目(Multi-Module Project)是其一个重要特性,它允许我们在一个项目中管理多个子模块。
在一个 Maven 多模块项目中,每个模块都是一个独立的项目,拥有自己的 POM 文件(Project Object Model,项目对象模型)。这些模块可以互相依赖,也可以被其他项目依赖。但是,所有的模块都会被统一管理,它们共享同一套构建系统和依赖管理。
Maven 多模块项目的结构是下面这样的:
在这个例子中,my-app 是父项目,my-module1 和 my-module2 是它的子模块。每个模块都有自己的 pom.xml 文件。
二、多模块项目优势有哪些
代码组织: 在大型项目中,我们经常需要把代码分成多个模块,以便更好地组织代码。每个模块可以聚焦于一个特定的功能或领域,这样可以提高代码的可读性和可维护性。
依赖管理: Maven 多模块项目可以帮助我们更好地管理项目的依赖。在父项目的 POM 文件中,我们可以定义所有模块共享的依赖,这样可以避免重复的依赖定义,也方便我们管理和升级依赖。
构建和部署: Maven 多模块项目的另一个优点是它可以统一管理项目的构建和部署。我们只需要在父项目中执行 Maven 命令,就可以对所有模块进行构建和部署。这大大简化了开发者的工作。
三、IDEA 搭建 Spring Boot 多模块工程
第一步:创建一个SpringBoot项目,设置好开发的统一版本,这里boot2.6.3,java1.8作为项目的父级。参考《SpringBoot笔记一》
Maven 仓库默认在国外, 国内使用难免很慢,我们可以更换为阿里云的仓库。
修改 maven 根目录下的 conf 文件夹中的 setting.xml 文件,在 mirrors 节点上,添加内容如下:
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
pom.xml文件里添加:
<repositories>
<repository>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
因为这是个父项目,专门负责统一管理子模块、依赖版本等,创建完成后,在左边导航栏中,先删除下图中标注的无用文件:
接下来,整理一下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 https://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.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ligoo</groupId>
<artifactId>hr</artifactId>
<version>${revision}</version>
<name>hr</name>
<!-- 项目描述 -->
<description>hr工作流程管理</description>
<!-- 多模块项目父工程打包模式必须指定为 pom -->
<packaging>pom</packaging>
<!-- 子模块管理 -->
<modules>
</modules>
<!-- <properties>-->
<!-- <java.version>1.8</java.version>-->
<!-- </properties>-->
<properties>
<!-- 项目版本号 -->
<revision>0.0.1-SNAPSHOT</revision>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Maven 相关 -->
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<!-- 统一依赖管理 -->
<dependencyManagement>
</dependencyManagement>
<build>
<!-- 统一插件管理 -->
<pluginManagement>
</pluginManagement>
</build>
<!-- <dependencies>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-web</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- </dependencies>-->
<!-- <build>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>-->
<!-- <repositories>-->
<!-- <repository>-->
<!-- <id>alimaven</id>-->
<!-- <name>aliyun maven</name>-->
<!-- <url>http://maven.aliyun.com/nexus/content/groups/public/</url>-->
<!-- <releases>-->
<!-- <enabled>true</enabled>-->
<!-- </releases>-->
<!-- <snapshots>-->
<!-- <enabled>false</enabled>-->
<!-- </snapshots>-->
<!-- </repository>-->
<!-- </repositories>-->
<repositories>
<repository>
<id>aliyunmaven</id>
<name>aliyun</name>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
</project>
解释说明:
pom.xml中的maven.compiler.source和maven.compiler.是用来编译源码和打包的,通常它们的版本等于系统JDK的大版本,如11,9,8...;
如果不能控制客户机的jdk,而想让包的适用性更广的话,可以手动降低版本号,比如如从11降到8;
如此做了后,在别的机器上运行自己的jar,就不会报jdk版本低的错误。
举例来说,我之前使用11打了个jar包,放到jdk=9的虚拟机上没法用,于是手动降低到8,因为代码中也确实没用到8后继版本的特性,于是再次打包后,虚拟机上再运行就可以了。
第二步:创建 web 前台功能模块(打包也在这个模块中进行)
接下来,我们开始创建父项目下面的子模块。在父项目上右键,添加模块 Module:
这里还是以java17创建模块,创建后再修改
创建后删除无用的文件,目录如下:
删除完成后,在父项目的 pom.xml 中添加该子模块,以及添加 spring-boot-maven-plugin :
spring-boot-maven-plugin是spring boot提供的maven打包插件。打包为可运行的jar包或war包
<!-- 子模块管理 -->
<modules>
<!-- 入口模块 -->
<module>web</module>
</modules>
<build>
<!-- 统一插件管理 -->
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
添加完父项目的 pom.xml后,开始编辑 web 模块中的 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父项目为 hr -->
<parent>
<groupId>com.ligoo</groupId>
<artifactId>hr</artifactId>
<version>${revision}</version>
</parent>
<groupId>com.ligoo</groupId>
<artifactId>web</artifactId>
<name>web</name>
<description>web(入口项目,负责前台相关功能,打包也放在这个模块负责)</description>
<dependencies>
<!-- Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
注意<relativePath/>这个标签只需要在父级项目中添加一次即可,子模块中是无需添加这个的,一定要去掉
这个<parent>下面的<relativePath>属性是什么意思呢,其实很明显,就是parent的路径,具体来说就是你引用这个parent项目,那parent项目的pom在哪里?
1、默认值
默认我们不用写<relativePath>,那默认值就是../pom.xml,会从上级目录中获取parent的pom,我们建多模块的项目就是这个情况。
2、<relativePath/>
这样写,也就是说我指定了relativePath,但值是空的,设定一个空值将始终从仓库中获取,不从本地路径获取。很常见的场景就是使用springboot的时候
3、<relativePath>路径<relativePath/>
这种也很显然,指定一个本地的路径,从本地路径获取parent的 pom。
第三步:创建 admin 后台管理模块。
同样的创建模块的步骤,创建admin模块,删除无用的文件结构如下:
修改父项目的pom.xml,添加admin子模块
<!-- 子模块管理 -->
<modules>
<!-- 入口模块 -->
<module>web</module>
<!-- 管理后台 -->
<module>admin</module>
</modules>
另外,还需要将 resource 目录下的配置文件,和 Application 启动类删除掉。配置文件统一放在 web 入口模块中来管理:
整理admin模块的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 指定父项目为 weblog-springboot -->
<parent>
<groupId>com.ligoo</groupId>
<artifactId>hr</artifactId>
<version>${revision}</version>
</parent>
<groupId>com.ligoo</groupId>
<artifactId>admin</artifactId>
<name>admin</name>
<description>admin (负责管理后台相关功能)</description>
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
第四步:创建 common 通用功能子模块
按照上面的步骤,再次创建 common 子模块,此模块专门用于存放一些通用的功能,如接口的日志切面、全局异常管理等等。
第五步:父项目统一版本管理
在父项目的 pom.xml 中,将这几个子模块统一声明一下,另外添加相关常用的工具包,统一版本管理,这里工具包暂时不填加,后面用到再做解释。
<!-- 统一依赖管理 -->
<dependencyManagement>
<dependencies>
<!--模块统一声明-->
<dependency>
<groupId>com.ligoo</groupId>
<artifactId>admin</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ligoo</groupId>
<artifactId>common</artifactId>
<version>${revision}</version>
</dependency>
<!--下面放置常用工具库-->
</dependencies>
</dependencyManagement>
第六步:子模块之间的依赖关系
这几个子模块之间,互相还存在依赖关系,我们也需要引入一下。
例如:web模块需要依赖common和admin,那么再web下面的pom.xml添加:
<dependencies>
<dependency>
<groupId>com.ligoo</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>com.ligoo</groupId>
<artifactId>admin</artifactId>
</dependency>
...
</dependencies>
例如:admin模块需要依赖common,那么再admin下面的pom.xml添加:
<dependencies>
<dependency>
<groupId>com.ligoo</groupId>
<artifactId>common</artifactId>
</dependency>
...
</dependencies>
第七步:测试运行和打包
①:执行 mvn clean 命令;
②:执行 mvn package 打包命令;
这里注意的是,企业开发中,一般都比较追求敏捷开发,可能不会写太多的单元测试。本实战项目同样为了追求进度,不会编写单元测试,所以多模块的单元测试并未配置完成。建议删掉单元测试再进行打包。
这样一个多模块的boot结构就形成了。这里需要掌握,父项目和子项目之间配置文件的内容,以及各个配置文件的作用。
以上本教程结束!!!