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、微服务模块拆分都游刃有余。