POM构造Spring boot多模块项目

基于Maven构建SpringBoot多模块项目(完整实操指南)

你想通过pom.xml搭建SpringBoot多模块项目,核心思路是拆分「父模块(统一管理依赖+版本)+ 子模块(按功能/分层拆分)」,既解耦代码,又能统一管理依赖版本,适配企业级开发规范。以下是从「空项目初始化 → 模块拆分 → 依赖配置 → 启动测试」的全流程。


一、多模块项目结构设计(通用规范)

先明确拆分逻辑,以你的UDP设备探测项目为例,推荐经典的4模块结构(可按需增减):

复制代码
udp-scan-parent(父模块,pom类型)
├── udp-scan-common(公共模块,jar类型:工具类、通用实体、常量)
├── udp-scan-mapper(数据层模块,jar类型:Mapper、MyBatis-Plus配置)
├── udp-scan-service(业务层模块,jar类型:Service接口/实现)
└── udp-scan-web(启动模块,jar类型:Controller、SpringBoot启动类、配置文件)
  • 父模块:仅管理依赖版本,不写业务代码;
  • 子模块 :按分层拆分,web模块是唯一的启动模块(含@SpringBootApplication)。

二、步骤1:创建父模块(pom.xml核心配置)

父模块的核心作用是统一管理依赖版本、插件版本,定义子模块继承规则 ,类型为pom(无源码,仅做依赖管理)。

1. 父模块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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 基础配置 -->
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging> <!-- 父模块必须为pom类型 -->
    <groupId>com.example</groupId> <!-- 公司/组织标识 -->
    <artifactId>udp-scan-parent</artifactId> <!-- 父模块名称 -->
    <version>1.0.0</version> <!-- 统一版本号 -->
    <name>udp-scan-parent</name>
    <description>UDP设备探测项目-父模块(统一依赖管理)</description>

    <!-- 1. 定义子模块(后续创建的子模块需在这里声明) -->
    <modules>
        <module>udp-scan-common</module>
        <module>udp-scan-mapper</module>
        <module>udp-scan-service</module>
        <module>udp-scan-web</module>
    </modules>

    <!-- 2. 继承SpringBoot父工程(统一SpringBoot版本) -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.1</version> <!-- SpringBoot版本(JDK17用3.x,JDK8用2.7.18) -->
        <relativePath/> <!-- 从Maven仓库拉取,不找本地路径 -->
    </parent>

    <!-- 3. 统一管理依赖版本(子模块直接用,无需写版本号) -->
    <dependencyManagement>
        <dependencies>
            <!-- 自定义子模块依赖(子模块间相互依赖时用) -->
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>udp-scan-common</artifactId>
                <version>${project.version}</version> <!-- 继承父模块版本 -->
            </dependency>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>udp-scan-mapper</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>udp-scan-service</artifactId>
                <version>${project.version}</version>
            </dependency>

            <!-- 第三方依赖版本管理(MyBatis-Plus、MySQL等) -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.5.5</version>
            </dependency>
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>8.0.33</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.30</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 4. 全局依赖(所有子模块都会继承,按需添加) -->
    <dependencies>
        <!-- Lombok(所有子模块都可能用到) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 测试依赖(所有子模块的测试都可用) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 5. 构建插件配置(统一编译、打包规则) -->
    <build>
        <plugins>
            <!-- SpringBoot打包插件(仅启动模块生效,父模块声明统一配置) -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.example.udp.web.UdpScanApplication</mainClass> <!-- 启动类全路径 -->
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal> <!-- 打包成可执行jar -->
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- 编译插件(指定JDK版本) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>17</source> <!-- JDK版本(17/8) -->
                    <target>17</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

关键配置说明

节点 作用 注意事项
<packaging>pom</packaging> 标记为父模块,仅管理依赖/子模块 父模块必须设为pom,子模块默认jar
<modules> 声明子模块名称,与子模块文件夹名一致 子模块创建后必须在这里声明,否则Maven无法识别
<dependencyManagement> 仅管理版本,不实际引入依赖 子模块需手动<dependency>引入,无需写版本号
<dependencies> 全局依赖,所有子模块自动继承 仅放所有子模块都需要的依赖(如lombok),避免冗余

三、步骤2:创建子模块(按分层拆分)

每个子模块的pom.xml只需继承父模块,按需引入依赖即可,无需重复定义版本号。

子模块1:udp-scan-common(公共模块)

作用:存放通用工具类、实体类、常量、枚举等,被其他子模块依赖。

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>
        <groupId>com.example</groupId>
        <artifactId>udp-scan-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath> <!-- 父模块pom.xml路径 -->
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>udp-scan-common</artifactId> <!-- 子模块名称 -->
    <name>udp-scan-common</name>
    <description>公共模块:工具类、实体类</description>

    <!-- 依赖:仅引入公共模块需要的依赖 -->
    <dependencies>
        <!-- SpringBoot核心(可选,若需要Spring相关工具) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 常用工具包(如hutool,可选) -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
        </dependency>
    </dependencies>
</project>

子模块2:udp-scan-mapper(数据层模块)

作用:存放Mapper接口、MyBatis-Plus配置、自定义SQL等,依赖common模块。

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>
        <groupId>com.example</groupId>
        <artifactId>udp-scan-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>udp-scan-mapper</artifactId>
    <name>udp-scan-mapper</name>
    <description>数据层:Mapper、MyBatis-Plus配置</description>

    <dependencies>
        <!-- 依赖公共模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>udp-scan-common</artifactId>
        </dependency>
        <!-- MyBatis-Plus(版本由父模块管理) -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
</project>

子模块3:udp-scan-service(业务层模块)

作用:存放Service接口/实现,依赖mapper模块。

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>
        <groupId>com.example</groupId>
        <artifactId>udp-scan-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>udp-scan-service</artifactId>
    <name>udp-scan-service</name>
    <description>业务层:Service接口/实现</description>

    <dependencies>
        <!-- 依赖公共模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>udp-scan-common</artifactId>
        </dependency>
        <!-- 依赖数据层模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>udp-scan-mapper</artifactId>
        </dependency>
        <!-- SpringBoot核心(业务层需要Spring容器) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>
</project>

子模块4:udp-scan-web(启动模块)

作用:存放Controller、启动类、配置文件,是唯一的启动模块,依赖service模块。

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>
        <groupId>com.example</groupId>
        <artifactId>udp-scan-parent</artifactId>
        <version>1.0.0</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>udp-scan-web</artifactId>
    <name>udp-scan-web</name>
    <description>启动模块:Controller、启动类、配置文件</description>

    <dependencies>
        <!-- 依赖公共模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>udp-scan-common</artifactId>
        </dependency>
        <!-- 依赖业务层模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>udp-scan-service</artifactId>
        </dependency>
        <!-- SpringBoot Web(Controller需要) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- 打包插件(继承父模块配置,可覆盖) -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <!-- 资源文件配置(读取application.yml) -->
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.yml</include>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

四、步骤3:项目目录结构与启动类

1. 最终目录结构(对应pom配置)

复制代码
udp-scan-parent/
├── pom.xml(父模块)
├── udp-scan-common/
│   ├── pom.xml
│   └── src/main/java/com/example/udp/common/
│       ├── entity/Device.java(通用实体)
│       ├── util/HttpUtil.java(工具类)
│       └── constant/Constants.java(常量)
├── udp-scan-mapper/
│   ├── pom.xml
│   └── src/main/java/com/example/udp/mapper/
│       ├── DeviceMapper.java(Mapper接口)
│       └── config/MyBatisPlusConfig.java(分页插件配置)
├── udp-scan-service/
│   ├── pom.xml
│   └── src/main/java/com/example/udp/service/
│       ├── DeviceService.java(接口)
│       └── impl/DeviceServiceImpl.java(实现)
└── udp-scan-web/
    ├── pom.xml
    └── src/main/
        ├── java/com/example/udp/web/
        │   ├── UdpScanApplication.java(启动类)
        │   └── controller/DeviceController.java(控制器)
        └── resources/application.yml(配置文件)

2. 启动类编写(udp-scan-web模块)

java 复制代码
package com.example.udp.web;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * 多模块项目启动类(核心:扫描所有子模块的包)
 */
@SpringBootApplication
// 扫描所有子模块的组件(com.example.udp下的所有包)
@ComponentScan(basePackages = "com.example.udp")
// 扫描Mapper接口(mapper模块)
@MapperScan(basePackages = "com.example.udp.mapper")
public class UdpScanApplication {
    public static void main(String[] args) {
        SpringApplication.run(UdpScanApplication.class, args);
    }
}

五、步骤4:编译与启动(验证多模块)

1. 编译打包(父模块根目录执行)

bash 复制代码
# 清理并编译所有模块
mvn clean compile

# 打包(web模块会生成可执行jar)
mvn clean package

2. 启动项目

  • IDEA中启动 :直接运行UdpScanApplication类,控制台无报错且能加载application.yml,说明多模块配置成功;

  • jar包启动 :进入udp-scan-web/target目录,执行:

    bash 复制代码
    java -jar udp-scan-web-1.0.0.jar

六、多模块配置避坑指南

1. 依赖循环问题

  • 禁止子模块相互依赖(如service依赖mapper,mapper又依赖service);
  • 通用逻辑放在common模块,避免循环依赖。

2. 包扫描问题

  • 启动类的@ComponentScan必须覆盖所有子模块的包(如com.example.udp);
  • @MapperScan必须扫描mapper模块的Mapper接口包,否则MyBatis-Plus无法识别。

3. 资源文件加载问题

  • 只有web模块需要放application.yml,其他模块无需配置文件;
  • 若其他模块有自定义配置文件,需在web模块通过@PropertySource加载。

4. 版本号统一问题

  • 所有子模块的版本号必须与父模块一致,推荐用${project.version}继承;
  • 第三方依赖版本统一在父模块dependencyManagement中管理,子模块不写版本号。

总结

  1. 多模块SpringBoot项目的核心是「父模块pom(管理依赖)+ 子模块jar(按分层拆分)」;
  2. 父模块关键配置:<packaging>pom</packaging> + <modules> + <dependencyManagement>
  3. 子模块关键:继承父模块 + 按需引入依赖 + 仅web模块作为启动模块;
  4. 启动类必须扫描所有子模块的包,否则组件/Mapper无法被Spring容器识别。
相关推荐
indexsunny2 小时前
互联网大厂Java面试实录:Spring Boot微服务在电商场景中的应用与挑战
java·spring boot·redis·mysql·security·microservices·interview
编程彩机2 小时前
互联网大厂Java面试:从分布式缓存到微服务架构的技术场景解析
java·redis·微服务·分布式事务·分布式缓存·面试解析
独自破碎E2 小时前
【字节面试手撕】大数加法
java·算法
鱼跃鹰飞2 小时前
LeetCode热题100: 49.字母异位词分组
java·数据结构·算法·leetcode
studyForMokey2 小时前
【Android面试】Java & Kotlin语言
android·java·面试
猿与禅2 小时前
Spring Boot 3.x 集成 Caffeine 缓存框架官方指南
spring boot·后端·缓存·caffeine
弹简特2 小时前
【Java-阔怕的JVM】JVM
java·开发语言·jvm
2301_780669862 小时前
UDP通信(一发一收,多发多收)、TCP通信(一发一收,多发多收、同时接收多个客户端的消息)、B/S架构的原理
java·tcp/ip·udp
小冷coding2 小时前
工作流是什么呢?
java·面试