1. 概述

本文将手把手带你搭建一个基于 Spring Boot 的多模块项目,适合想搞清模块化结构、避免“大泥球”架构的开发者。

核心思路很清晰:
✅ 先做一个纯 library 模块(非可执行 Jar)
✅ 再做一个 application 模块,依赖并使用上面的 library

如果你还不熟悉 Spring Boot 基础,建议先看这篇入门文章:Spring Boot 快速开始

⚠️ 本文假设你已掌握 Maven 基本操作,不再赘述 mvn clean install 这种基础命令。


2. 项目结构搭建

我们先创建一个 聚合型 parent 模块,用 pom 打包方式来管理子模块。

<groupId>com.baeldung</groupId>
<artifactId>parent-multi-module</artifactId>
<packaging>pom</packaging>

然后在项目根目录下创建两个子模块目录:

parent-multi-module/
├── library/
├── application/
└── pom.xml

在根 pom.xml 中声明子模块:

<modules>
    <module>library</module>
    <module>application</module>
</modules>

这样 Maven 就知道要构建哪些子项目了。


3. Library 模块开发

这个模块的目标是封装通用能力,比如工具类、服务逻辑、自定义 Starter 等。

3.1 基础配置

library/pom.xml 配置如下:

<groupId>com.baeldung.example</groupId>
<artifactId>library</artifactId>
<packaging>jar</packaging>

为了享受 Spring Boot 的依赖版本管理红利,我们引入 spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</version>
    <relativePath/>
</parent>

<relativePath/> 留空:告诉 Maven 到远程仓库找 parent,而不是本地相对路径

3.2 替代方案:使用 BOM 导入(推荐)

如果你的公司有统一的 parent POM,不能直接继承 spring-boot-starter-parent,那就用 BOM 方式导入依赖管理

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <type>pom</type>
            <version>3.1.5</version>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这种方式更灵活,适合大型组织架构。

3.3 依赖与代码实现

只引入最基础的 starter:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
</dependencies>

⚠️ 注意:**不要加 spring-boot-maven-plugin**!
因为 library 不需要打包成可执行 über-jar,加了反而可能引发 classpath 冲突。

接下来写一个简单服务类:

@Service
public class EvenOddService {

    public String isEvenOrOdd(Integer number) {
        return number % 2 == 0 ? "Even" : "Odd";
    }
}

这个类会被 application 模块通过依赖注入使用。


4. Application 模块开发

这才是真正的可运行 Spring Boot 应用。

4.1 基础配置

application/pom.xml 结构类似:

<groupId>com.baeldung.example</groupId>
<artifactId>application</artifactId>
<packaging>jar</packaging>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</version>
    <relativePath/>
</parent>

4.2 添加依赖

关键点来了:必须显式依赖我们自己的 library 模块

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baeldung.example</groupId>
        <artifactId>library</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>

✅ 使用 ${project.version}:确保版本一致,避免踩坑

4.3 启用 Spring Boot 插件

一定要加上这个插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

它的三大作用你得记牢:

功能 说明
✅ 依赖对齐 自动匹配 Spring Boot 推荐版本
✅ 主类识别 扫描 main() 方法,标记可执行入口
✅ 打包 über-jar 把所有依赖打成一个 fat jar,部署简单粗暴

4.4 编写主类和接口

直接上代码,一气呵成:

@SpringBootApplication(scanBasePackages = "com.baeldung")
@RestController
public class EvenOddApplication {

    private final EvenOddService evenOddService;

    public EvenOddApplication(EvenOddService evenOddService) {
        this.evenOddService = evenOddService;
    }

    @GetMapping("/validate/")
    public String isEvenOrOdd(@RequestParam("number") Integer number) {
        return evenOddService.isEvenOrOdd(number);
    }

    public static void main(String[] args) {
        SpringApplication.run(EvenOddApplication.class, args);
    }
}

💡 scanBasePackages = "com.baeldung":确保能扫到 library 包下的 @Service

启动后访问:
👉 http://localhost:8080/validate/?number=5 → 返回 "Odd"
👉 http://localhost:8080/validate/?number=4 → 返回 "Even"

一切正常!


5. 总结

多模块项目不是花架子,而是中大型系统的标配。本文的关键点总结如下:

  • parent 模块用 pom 打包,仅做聚合
  • library 模块不要加 spring-boot-maven-plugin
  • application 模块必须加插件,生成 über-jar
  • 依赖版本统一管理:优先用 BOM 方式导入,兼容性更好
  • 包扫描范围要覆盖所有模块,避免 Bean 找不到

所有示例代码已上传至 GitHub:https://github.com/baeldung/tutorials/tree/master/spring-boot-modules/spring-boot-custom-starter

搞懂这套结构,后续做自定义 Starter、微服务模块拆分都游刃有余。


原始标题:Multi-Module Project With Spring Boot