Springboot+Maven多模块项目开发

Springboot+Maven多模块项目开发


前言

1.多模块项目的好处:

  • 代码复用

一个后端项目的entity、dao、service代码需要用到前端服务,还需要用到后台管理,通过多模块可实现复用

  • 减少build时间

只需要build改动到的模块

  • 模块化代码不容易造成版本冲突

2.示例结构:
继承 聚合 继承 聚合 聚合 继承 依赖 依赖 <<pom>> Parent <<需要单独运行的jar>> ModuleOne <<公共部分功能且无需单独运行的jar>> Common <<需要单独运行的jar>> ModuleTwo

  • Parent:

pom项目

作用:1.聚合子模块,自动管理子模块打包顺序等;2.进行总的依赖库版本管理

特别:不需要单独运行,没有启动类

  • Common:

公共部分功能且无需单独运行的jar模块

作用:提取出的公共功能模块,被其他子模块依赖使用

特别:不需要单独运行,没有启动类

  • ModuleOne:

业务功能需要单独运行的jar模块

作用:某一业务的运行模块,比如前端API服务

特别:需要单独运行,有启动类

  • ModuleTwo:

业务功能需要单独运行的jar模块

作用:某一业务的运行模块,比如后端管理系统

特别:需要单独运行,有启动类

示例项目建设

示例代码仓库:https://gitee.com/x-shungeer/hello-cloud/tree/master/00 mutil-module-demo

Parent项目

利用Spring Initializr建立基于Maven的项目

Parent项目能够聚合子模块,聚合后能够批处理所有子模块,比如:
ModuleOne模块依赖Common模块,Maven打包ModuleOne时,需要先install模块Common,否则就会报错,当ModuleOne模块依赖的模块很多时,此步骤就显得耗时耗力了。使用Parent项目能够自动处理这个问题。

Spring Initializr脚手架URL:

1.https://start.spring.io

2.httpw://start.aliyun.com

针对Parent项目的pom.xml:

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>

    <!-- 指定该项目打包类型。pom 表示这是一个父项目(也称为聚合项目),它通常不包含可执行的代码,而是用于管理和组织多个子模块 -->
    <packaging>pom</packaging>

    <parent>
    	<!-- 源头是spring-boot-dependencies,定义了当前SpringBoot版本能用到的所有依赖及其适配的版本号 -->
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.6</version>
        <!-- 指定父模块pom.xml相对位置,若父模块pom.xml与子模块文件夹属于同一目录,则不用指定该值 -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.study.hello</groupId>
    <artifactId>mutil-module-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>00 mutil-module-demo</name>
    <description>00 mutil-module-demo</description>

    <!-- 父模块的properties也是向下继承的 -->
    <properties>
        <java.version>11</java.version>
        <project.encode>UTF-8</project.encode>
        <project.build.sourceEncoding>${project.encode}</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${project.encode}</project.reporting.outputEncoding>
    </properties>

    <!-- 父模块依赖,被所有子模块共用的 -->
    <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>

    <!-- 依赖版本管理,管理子模块对应依赖的版本 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.73</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.24</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

	<!-- 只有声明在父模块pom.xml文件的modules中的子模块,才会被构建 -->
    <modules>
        <module>module-common</module>
        <module>module-one</module>
        <module>module-two</module>
    </modules>
</project>

Common模块

pom.xml:

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.study.hello</groupId>
        <artifactId>mutil-module-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.study.hello</groupId>
    <artifactId>module-common</artifactId>
    <!-- 子模块可以不声明version,这样该模块直接继承父模块版本号,其余子模块同理 -->
    <version>0.0.1-SNAPSHOT</version>
    <name>module-common</name>
    <description>module-common</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

ModuleOne模块

pom.xml:

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.study.hello</groupId>
        <artifactId>mutil-module-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.study.hello</groupId>
    <artifactId>module-one</artifactId>
    <!-- 子模块可以不声明version,这样该模块直接继承父模块版本号,其余子模块同理 -->
    <version>0.0.1-SNAPSHOT</version>
    <name>module-one</name>
    <description>module-one</description>

    <dependencies>
        <dependency>
            <groupId>com.study.hello</groupId>
            <artifactId>module-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!-- 由于在父模块dependencyManagement中声明了这个依赖的版本,因此子模块引入这个依赖不需要声明版本号,构建引入时会自动向上查找父模块dependencyManagement中对应依赖的版本 -->

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <!--注意:这个地方的junit是没有版本号的,
        maven会自动的向上找,找到<dependencyManagerment>标签并使用它里面声明的依赖的版本号-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 指定打包时 jar的输出位置 -->
                    <!-- <outputDirectory>../target</outputDirectory> -->

                    <!--<mainClass>com.study.hello.ModuleCommonApplication</mainClass>-->
                    <!--<classifier>exec</classifier>-->
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!-- 可以把依赖的包都打包到生成的jar包中 -->
                            <!-- <goal>repackage</goal> -->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

特别说明

1.Parent项目继承自spring-boot-starter-parent,源头是spring-boot-dependencies,定义了当前SpringBoot版本能用到的所有依赖及其适配的版本号。此处也可以不继承spring-boot-starter-parent,而是在标签<dependencyManagement>内定义子模块用到的所有Springboot的依赖版本,如下述代码所示。


2.<relativePath/>标签可以指定父模块pom.xml文件所在的相对路径。基准目录是:子模块文件夹与父模块的pom.xml所在的同一目录,此时可以不指定标签的值,其他情况下需要根据此基准目录指定相对目录。例如父模块的pom.xml文件位于子模块文件夹的上两级目录,此时的标签值为:../../pom.xml


3.<modules><parent>两个标签的组合拳:<parent>标签声明继承,主要继承属性、依赖等等父模块的属性,而父模块中的<modules>是指定哪些子模块会随着该父模块一起被构建。所以,如果在项目中存在用于测试的子模块需要继承父模块,但是又不希望这些模块最后被构建,就可以在父模块中的<modules>删除这些子模块的声明。


4.<dependencies>管理所有子模块的共用依赖,也可以在此指定当前模块的依赖包,父模块<dependencies>所定义的依赖包都会被子模块所继承。


5.<dependencyManagement>管理子模块不共用的依赖库版本。这样的好处是:当模块增多时,不用一个个去修改一些不共用的依赖库版本,在<dependencyManagement>中修改即可。当父模块的pom.xml定义好<dependencyManagement>依赖库版本后,子模块在<dependencies>中直接指定依赖库名字,而不用指定版本,Maven会自动去父模块的<dependencyManagement>中定位。当然,所某个子模块不想使用父模块<dependencyManagement>指定的依赖库版本,子模块可以在<dependencies>中指定自己的版本。


6.Common模块不指定<build>标签,否则ModuleA模块和ModuleB模块build时会提示错误:Unable to find main class。这是因为spring-boot-maven-plugin打成的jar包可以运行,但是不能被其他工程依赖。此外Common模块不指定@SpringBootTest,否则会提示错误:java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

<dependencyManagement>内定义子模块用到的所有Springboot的依赖版本的代码:

xml 复制代码
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.6.RELEASE</version>
                <!--<type>pom</type>配合<scope>import</scope>标签可以额外引入其他的pom文件中的<dependencyManagement>内容,解决了maven单继承的问题。-->
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

参考:

1、https://blog.csdn.net/m0_71777195/article/details/131592022

2、https://blog.csdn.net/qq_40925189/article/details/103842208

相关推荐
用户83071968408213 小时前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解13 小时前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解14 小时前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记17 小时前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者1 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840821 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解2 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者2 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq
花花无缺2 天前
搞懂@Autowired 与@Resuorce
java·spring boot·后端
Derek_Smart2 天前
从一次 OOM 事故说起:打造生产级的 JVM 健康检查组件
java·jvm·spring boot