Spring Boot 多模块
Spring Boot 多模块项目是一种将大型项目拆分成多个小型、独立且相互协作的模块的开发方式。这种架构可以提高代码的可维护性、可扩展性和团队协作效率。下面从创建、结构、模块间依赖、配置管理以及打包部署等方面详细介绍 Spring Boot 多模块项目。
多模块项目的核心优势包括:
- 分而治之:将大项目拆分为多个模块,减少模块之间的耦合,提高可维护性。
- 独立开发:各模块可以独立开发和测试,便于团队协作。
- 重用性:模块可以在其他项目中复用,提高开发效率。
1. 创建 Spring Boot 多模块项目
1.1 使用 Spring Initializr
可以通过 Spring Initializr(https://start.spring.io/ )创建一个父项目。在创建时选择 Maven 或 Gradle 作为构建工具,选择合适的 Spring Boot 版本,添加必要的依赖。在项目结构上,选择创建一个多模块项目。
1.2 手动创建
如果你想手动创建,可以先创建一个空的 Maven 或 Gradle 项目作为父项目,然后在父项目的 pom.xml
(Maven)或 build.gradle
(Gradle)中配置子模块信息。
- 设置父项目的
pom.xml
文件,指定打包方式为pom
,并声明子模块。
Maven 示例:
<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>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
<packaging>pom</packaging>
<!-- 声明子模块,在总工程中配置 modules, 将各个模块工程汇集起来,作为一个整体对应完整的项目-->
<modules>
<module>module1</module>
<module>module2</module>
</modules>
</project>
2.项目结构
一个典型的 Spring Boot 多模块项目结构如下:
parent-project
├── pom.xml
├── module1
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ ├── resources
│ │ └── test
│ │ ├── java
│ │ └── resources
│ └── pom.xml
├── module2
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ ├── resources
│ │ └── test
│ │ ├── java
│ │ └── resources
│ └── pom.xml
-
父项目(
parent-project
):主要用于管理子模块的公共配置和依赖,packaging
类型为pom
。 -
子模块(
module1
、module2
):每个子模块有自己独立的代码和配置,可以有不同的功能,如数据访问、业务逻辑、Web 接口等。子模块
pom.xml
配置:
<!--使用parent标签指定当前工程的父工程-->
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<!-- 子工程的坐标 -->
<!-- 如果子工程中的groupId 和version 和父工程一致,那么可以省略-->
<artifactId>module1</artifactId>
<!-- <groupId>com.example</groupId> 与父工程一致,那么可以省略-->
<!-- <version>1.0.0</version> 与父工程一致,那么可以省略-->
3. 模块间依赖
3.1 声明依赖
在 Maven 中,可以在子模块
的 pom.xml
中声明对其他子模块的依赖。
例如,module2
依赖 module1
:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>module1</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
3.2 依赖范围
不同的依赖范围(如 compile
、runtime
、test
等)决定了依赖在不同阶段的可用性。例如,compile
范围的依赖在编译和运行时都可用,而 test
范围的依赖只在测试阶段可用。
4. 配置管理
4.1 公共配置
**父项目
**的 pom.xml
可以定义公共的依赖、插件和属性,子模块可以继承这些配置。例如:
<!-- 通过自定义属性,统一指定依赖的版本 -->
<properties>
<java.version>1.8</java.version>
<!-- 自定义标签,维护版本数据 -->
<spring-boot.version>2.5.4</spring-boot.version>
</properties>
<!--使用dependencyManagement标签配置对依赖的管理,
统一管理子模块的依赖版本,确保子模块使用相同版本的依赖。-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 引用上处自定义标签,维护版本数据 -->
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
(1)dependencyManagement
为了保持模块间依赖统一,在父模块中使用dependencyManagement预定义
所有模块需要用到的dependency(依赖),然后,子model根据实际需要
引入parent中预定义的依赖
好处:
-
依赖统一管理(parent中定义,需要变动dependency版本,只要修改一处即可);
-
代码简洁(子model只需要指定groupId、artifactId即可)
-
dependencyManagement只会影响现有依赖的配置,但不会引入依赖,即子model不会继承parent中dependencyManagement所有预定义的depandency,只引入需要的依赖即可,
简单说就是“
按需引入依赖
”或者“按需继承
”;因此,在parent中严禁直接使用depandencys预定义依赖,坏处是子model会自动继承depandencys中所有预定义依赖;
(2)packaging
packaging默认类型jar
类型,如果不做配置,maven会将该项目打成jar
包。
常见项目的打包类型:pom
、jar
、war
:
- pom ---------> 父类型都为pom类型
- jar ---------> 内部调用或者是作服务使用
- war ---------> 需要部署的项目(一般web相关)
小结:父级项目里packaging打包方式一般配置成pom,pom 表示项目里没有java代码,也不执行任何代码,只是为了聚合工程或传递依赖用的。
(3)modules
管理子项目
(4)build
在SpringBoot项目的pom.xml文件中,元素用于定义项目的构建配置,主要包括插件和资源过滤等配置。出现在pom.xml的顶层元素中,是一个重要的构建配置区。
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<filtering>true</filtering>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
4.2 模块特定配置
每个子模块可以有自己的配置文件,如 application.properties
或 application.yml
,用于配置该模块特有的属性。
5. 打包部署
5.1 打包
在父项目根目录下执行 mvn clean package
(Maven)或 gradle build
(Gradle)命令,Maven 或 Gradle 会自动按顺序打包各个子模块。最终会在每个子模块的 target
目录下生成对应的 JAR 或 WAR 文件。
5.2 部署
根据项目需求,可以将不同的子模块部署到不同的服务器或容器中。例如,Web 模块可以部署到 Tomcat 或嵌入式的 Spring Boot 服务器中,而数据访问模块可以作为依赖被其他模块引用。
6. 示例代码
6.1 module1
定义服务接口
package com.example.module1.service;
public interface HelloService {
String sayHello();
}
package com.example.module1.service.impl;
import com.example.module1.service.HelloService;
public class HelloServiceImpl implements HelloService {
@Override
public String sayHello() {
return "Hello from Module 1!";
}
}
6.2 module2
使用 module1
的服务
package com.example.module2.controller;
import com.example.module1.service.HelloService;
import com.example.module1.service.impl.HelloServiceImpl;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
private final HelloService helloService = new HelloServiceImpl();
@GetMapping("/hello")
public String hello() {
return helloService.sayHello();
}
}
7. 注意事项
- 版本管理:确保父项目和子模块中依赖的版本一致,避免版本冲突。
- 循环依赖:避免模块之间出现循环依赖,这会导致项目结构混乱和难以维护。
- 模块划分原则:根据功能、业务领域等合理划分模块,每个模块应具有高内聚、低耦合的特点。
通过 Spring Boot 多模块项目的方式,可以更好地组织和管理大型项目,提高开发效率和代码质量。