多模块项目是项目构建中的概念。拿 Maven 来说,多模块项目(Multi-Module Project)是其一个重要特性,它允许我们在一个项目中管理多个子模块。

在一个 Maven 多模块项目中,每个模块都是一个独立的项目,拥有自己的 POM 文件(Project Object Model,项目对象模型)。这些模块可以互相依赖,也可以被其他项目依赖。但是,所有的模块都会被统一管理,它们共享同一套构建系统和依赖管理。

Maven 多模块项目的结构大概是下面这样的:

my-app/  (父项目)
  |- pom.xml
  |- my-module1/  (子模块1)
  |    |- pom.xml
  |- my-module2/  (子模块2)
       |- pom.xml
  | ... (实际企业级项目中,会分非常多的模块)     

在这个例子中,my-app 是父项目,my-module1my-module2 是它的子模块。每个模块都有自己的 pom.xml 文件。

多模块项目的好处

  • 代码组织:在大型项目中,我们经常需要把代码分成多个模块,以便更好地组织代码。每个模块可以聚焦于一个特定的功能或领域,这样可以提高代码的可读性和可维护性。
  • 依赖管理:Maven 多模块项目可以帮助我们更好地管理项目的依赖。在父项目的 POM 文件中,我们可以定义所有模块共享的依赖,这样可以避免重复的依赖定义,也方便我们管理和升级依赖。
  • 构建和部署:Maven 多模块项目的另一个优点是它可以统一管理项目的构建和部署。我们只需要在父项目中执行 Maven 命令,就可以对所有模块进行构建和部署。这大大简化了开发者的工作。

创建WeBlog多模块项目

父项目创建

在一个位置创建一个文件夹WeBlog之后,先建父项目:

作为父项目目前不需要添加任何依赖,并且只保留以下目录即可:

修改pom.xml,添加 packing 标签并设定内容为 pom:

<groupId>com.weblog</groupId>  
<artifactId>weblog-springboot</artifactId>  
<version>${revision}</version>  
<name>weblog-springboot</name>  
<description>前后端分离博客 Weblog</description>
 
<!-- 多模块项目父工程打包模式必须指定为 pom --><packaging>pom</packaging>
 
<!-- 版本号统一管理 -->  
<properties>  
    <!-- 项目版本号 -->  
    <revision>0.0.1-SNAPSHOT</revision>  
    <java.version>17</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>

Web 访问模块

在父项目上右键,添加模块 Module,还是和上面创建父项目差不多的步骤,命名一个 weblog-web 模块,此模块是项目的入口,Maven 打包的打包插件放在这里,同时,和博客前台页面展示相关的功能也统一放在此模块下,勾选上 LombokSpring Web 依赖,点击 create 创建模块,删除一些无用目录后结果如下:

在父项目的 pom.xml 中添加该子模块,以及添加 spring-boot-maven-plugin

<!-- 子模块管理 -->  
<modules>  
    <!-- 入口模块 -->  
    <module>weblog-web</module>  
</modules>  
 
  
<build>  
    <pluginManagement>  
        <plugins>  
            <plugin>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-maven-plugin</artifactId>  
                <configuration>  
                    <excludes>  
                        <exclude>  
                            <groupId>org.projectlombok</groupId>  
                            <artifactId>lombok</artifactId>  
                        </exclude>  
                    </excludes>  
                </configuration>  
            </plugin>  
        </plugins>  
    </pluginManagement>  
</build>

接着修改子模块的pom.xml,指定父模块还有需要用到的依赖:

<parent>  
    <groupId>com.weblog</groupId>  
    <artifactId>weblog-springboot</artifactId>  
    <version>${revision}</version>  
<!-- lookup parent from repository -->  
</parent>  
  
<artifactId>weblog-web</artifactId>  
<name>weblog-web</name>  
<description>weblog-web (入口项目,负责博客前台展示相关功能,打包也放在这个模块负责)</description>
<dependencies>  
    <dependency>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-starter-web</artifactId>  
    </dependency>  
  
    <dependency>  
       <groupId>org.projectlombok</groupId>  
       <artifactId>lombok</artifactId>  
       <optional>true</optional>  
    </dependency>  
</dependencies>  
  
<build>  
    <plugins>  
       <plugin>  
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-maven-plugin</artifactId>  
       </plugin>  
    </plugins>  
</build>

Admin 管理后台功能模块

新建一个负责 Admin 管理后台功能的子模块,命名为 weblog-module-admin ,此模块用于统一放置和 Admin 管理后台相关的功能,仅需勾选 Lombok,同样删除无用文件夹后,还需要将 resource 目录下的配置文件,和 Application 启动类删除掉。配置文件统一放在 weblog-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>  
    <parent>  
       <groupId>com.weblog</groupId>  
       <artifactId>weblog-springboot</artifactId>  
       <version>${revision}</version><!-- lookup parent from repository -->  
    </parent>  
  
    <artifactId>weblog-model-admin</artifactId>  
    <name>weblog-model-admin</name>  
    <description>weblog-model-admin 统一放置和 Admin 管理后台相关的功能</description>  
    <properties>  
       <java.version>17</java.version>  
    </properties>  
    <dependencies>  
       <dependency>  
          <groupId>org.projectlombok</groupId>  
          <artifactId>lombok</artifactId>  
          <optional>true</optional>  
       </dependency>  
       <dependency>  
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-starter-test</artifactId>  
       </dependency>  
    </dependencies>  
</project>

common 通用功能子模块

创建 weblog-module-common 子模块,此模块专门用于存放一些通用的功能,如接口的日志切面、全局异常管理等等。

其 Pom:

<?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>com.weblog</groupId>  
       <artifactId>weblog-springboot</artifactId>  
       <version>${revision}</version><!-- lookup parent from repository -->  
    </parent>  
  
    <artifactId>weblog-module-common</artifactId>  
    <name>weblog-module-common</name>  
    <description>weblog-module-common 用于存放一些通用的功能,如接口的日志切面、全局异常管理等等</description>  
  
    <dependencies>  
    </dependencies>  
  
    <build>  
       <plugins>  
          <plugin>  
             <groupId>org.springframework.boot</groupId>  
             <artifactId>spring-boot-maven-plugin</artifactId>  
          </plugin>  
       </plugins>  
    </build>  
  
</project>

父项目统一版本管理

在父项目的 pom.xml 中,将这几个子模块统一声明一下,另外添加相关常用的工具包,如 commons-lang3guava

<!-- 版本号统一管理 -->  
<properties>
	...
	<!-- 依赖包版本 -->  
	<lombok.version>1.18.30</lombok.version>  
	<guava.version>31.1-jre</guava.version>  
	<commons-lang3.version>3.12.0</commons-lang3.version>
</properties>
<dependencyManagement>  <!-- 没有这个就是直接添加到所有子模块的依赖中 -->  
	<dependencies>  
	    <dependency>  
	        <groupId>com.weblog</groupId>  
	        <artifactId>weblog-module-admin</artifactId>  
	        <version>${revision}</version>  
	    </dependency>  
	    <dependency>  
	        <groupId>com.weblog</groupId>  
	        <artifactId>weblog-module-common</artifactId>  
	        <version>${revision}</version>  
	    </dependency>  
	    <dependency>  
	        <groupId>com.weblog</groupId>  
	        <artifactId>weblog-web</artifactId>  
	        <version>${revision}</version>  
	    </dependency>  
	  
	    <!-- 免写冗余的 Java 样板式代码 -->  
	    <dependency>  
	        <groupId>org.projectlombok</groupId>  
	        <artifactId>lombok</artifactId>  
	        <optional>true</optional>  
	        <version>${lombok.version}</version>
	    </dependency>  
	    <!-- 单元测试 -->  
	    <dependency>  
	        <groupId>org.springframework.boot</groupId>  
	        <artifactId>spring-boot-starter-test</artifactId>  
	        <scope>test</scope>  
	    </dependency>  
	  
	    <!-- 常用工具库 -->  
	    <dependency>  
	        <groupId>com.google.guava</groupId>  
	        <artifactId>guava</artifactId>  
	        <version>${guava.version}</version>  
	    </dependency>  
	    <dependency>  
	        <groupId>org.apache.commons</groupId>  
	        <artifactId>commons-lang3</artifactId>  
	        <version>${commons-lang3.version}</version>  
	    </dependency>  
	</dependencies>
</dependencyManagement>

子模块之间的依赖关系

这几个子模块之间,互相还存在依赖关系,我们也需要引入一下。如入口模块 weblog-web 依赖于 weblog-module-adminweblog-module-common,在其 pom.xml 添加如下:

<dependencies>  
    <dependency>  
       <groupId>org.springframework.boot</groupId>  
       <artifactId>spring-boot-starter-web</artifactId>  
    </dependency>  
    <dependency>  
       <groupId>com.weblog</groupId>  
       <artifactId>weblog-module-common</artifactId>  
    </dependency>  
    <dependency>  
       <groupId>com.weblog</groupId>  
       <artifactId>weblog-module-admin</artifactId>  
    </dependency>  
</dependencies>

以及 weblog-module-admin 依赖于 weblog-module-common,在其 pom.xml 添加如下: