上一篇:后端笔记之Maven配置以及解决Maven中央仓库没有的依赖
上一篇里提到依赖时,子模块会继承父项目的驱动依赖,因为项目是多模块结构,该篇区分Maven多模块与微服务 。

Maven 多模块 = 代码层面拆分;微服务 = 运行时独立部署拆分。
现在项目只是代码仓库内分层,所有模块最终打包后依然跑在同一个进程、同一个服务实例里,这叫模块化单体项目,不是微服务。
一、结构
1、Maven 多模块
bash
parent(父工程,统一管理版本)
├─ module-api 接口、DTO实体类
├─ module-service 业务逻辑
├─ module-mapper 数据库操作
└─ module-web 启动类、Controller
本质特点:
- 只是代码组织方式:把代码分成不同子模块,方便包管理、依赖隔离;
- 最终打成一个 Jar;
- 只有一个 main 启动类,启动之后所有模块代码运行在同一个 JVM 进程;
- 模块之间调用:本地 Java 方法直接调用,不存在网络请求、远程调用。
调用方式:A模块直接new对象 / Spring注入调用B模块方法,进程内调用,没有 HTTP/RPC。
bash
类比:一栋大房子,只是室内用墙隔成客厅、卧室、厨房,房子仍然是一栋建筑,进出同一个大门。

2、微服务
微服务每一个业务模块独立工程、独立仓库(或独立子项目)、独立启动类、独立打包、独立进程、独立端口。
bash
订单服务(独立jar,8081端口,单独启动)
用户服务(独立jar,8082端口,单独启动)
库存服务(独立jar,8083端口,单独启动)
- 服务和服务之间:跨进程网络调用(OpenFeign/Dubbo RPC)
- 一个服务崩溃,理论上不直接拖垮其他服务
- 可以单独部署、单独扩容
bash
类比:直接拆成好几栋独立小屋,每栋房子单独大门,屋子之间交流需要打电话(网络请求)。
3、两者关键对比表

4、 误区
误区:代码分成多个 maven 子模块 = 微服务
真相:代码分层 ≠ 服务拆分
新手项目:
用 maven 多模块分出 user、order 模块,就自称微服务。
但是:所有模块打包进同一个 jar,一起启动,模块之间直接本地调用。
这只是工程代码模块化,架构依旧是单体架构。
5、例子
场景:电商下单
① Maven 多模块单体(你的项目)
web 模块收到请求 → 本地调用 order 模块方法 → 本地调用 stock 模块扣库存
全程:进程内方法调用,没有网络。
② 微服务架构
网关接收请求 → 调用【订单服务 (8081)】 → 订单服务通过 HTTP/RPC 远程请求【库存服务 (8082)】
两次不同进程之间网络通信。
6、延伸:「多模块单体」改成真正微服务
把 order、user 等子模块,抽离成独立 SpringBoot 项目,各自拥有启动类;
模块间本地方法调用,改成远程调用(Dubbo / OpenFeign);
引入注册中心 Nacos、网关、服务治理组件;
每个服务独立打包、独立部署。
7、总结
Maven 多模块只是源代码层面的逻辑分层,用来规范代码结构、统一依赖管理;所有子模块最终合并运行在同一个进程,不存在跨服务网络调用。
微服务是部署运行层面的物理拆分,业务单元独立进程、独立部署,依靠网络完成互相通信。
二者维度完全不同,不能混为一谈。
二、差异
代码层面(pom.xml + 工程结构 + 打包运行逻辑)三处决定性差异
① 普通 Maven 多模块(单体架构常用)
场景:项目拆多个模块,最终只会打出 1 个可执行 Jar
例如:父 pom → core、dao、web;只有 web 模块带启动类,其他都是 jar 依赖。
运行:一个进程。
② SpringCloud Maven 多模块(微服务聚合工程)
场景:父 pom 聚合,每一个 service 子模块都是独立 SpringBoot 应用,各自打包独立 Jar、独立进程、独立部署。
运行:N 个进程。
1、pom.xml 代码上直观区别
区别 1:modules 内子模块定位不同
(1)【普通多模块(单体)】结构
bash
parent(pom)
├─ module-core jar包,工具/实体
├─ module-dao jar包,持久层
└─ module-web 唯一带启动类、唯一可执行模块
父 pom modules 列表:
xml
<modules>
<module>module-core</module>
<module>module-dao</module>
<module>module-web</module>
</modules>
bash
只有 module-web 能运行;core/dao 仅仅是依赖库,不能单独启动。
(2)【SpringCloud 微服务多模块】结构
bash
parent(pom)
├─ spring-cloud-common 公共jar库(无启动类)
├─ spring-cloud-gateway 独立应用,可启动
├─ spring-cloud-service-user 独立应用,可启动
└─ spring-cloud-service-order 独立应用,可启动
父 pom modules 列表:
xml
<modules>
<module>spring-cloud-common</module>
<module>spring-cloud-gateway</module>
<module>spring-cloud-service-user</module>
<module>spring-cloud-service-order</module>
</modules>
bash
gateway / user / order 全部拥有独立启动类,均可单独打包、单独启动
区别 2:子模块 pom 打包插件配置差异
普通单体多模块
- core、dao:没有 spring-boot-maven-plugin
- 仅 web 模块存在打包插件,最终构建出唯一可执行 jar
xml
<!-- 仅web模块才有 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
SpringCloud 微服务多模块
- 所有业务服务模块(gateway、user、order)各自都配置 spring-boot-maven-plugin
- 每个模块都能独立打成可执行 jar:
xml
<!-- service-user pom -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.demo.cloud.user.UserApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
bash
common 模块依然不加此插件,只是基础依赖包。
区别 3:依赖清单代码差异
普通单体多模块 web 模块依赖
只有基础 web、mybatis,没有微服务组件
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.xxx</groupId>
<artifactId>module-core</artifactId>
</dependency>
</dependencies>
SpringCloud 微服务模块依赖
多出Spring Cloud 微服务生态依赖(代码层面最明显标识)
xml
<!-- 注册中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- 配置中心 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 远程调用 OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
区别 4:启动类注解代码区别
普通单体项目启动类
java
@SpringBootApplication
public class WebApplication {
public static void main(String[] args) {
SpringApplication.run(WebApplication.class, args);
}
}
SpringCloud 微服务启动类
增加微服务相关注解(代码特征)
java
@SpringBootApplication
@EnableDiscoveryClient // 服务注册到注册中心
@EnableFeignClients // 开启远程调用
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
区别 5:配置文件差异
普通单体:application.yml
微服务:通常配套 bootstrap.yml(用于 Nacos 配置中心加载),配置内包含服务名、nacos 地址
yaml
spring:
application:
name: service-user # 服务唯一名称,注册中心识别
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
2、Maven 命令构建行为差异
普通单体多模块
执行 mvn clean package
- 先编译 core → dao
- 最后打包 web
产物只有一个可执行 jar:module-web.jar
启动:java -jar module-web.jar 只启动一个进程
SpringCloud 微服务聚合多模块
执行 mvn clean package
产物:
- spring-cloud-common.jar(普通依赖包)
- spring-cloud-gateway.jar(可执行)
- spring-cloud-service-user.jar(可执行)
- spring-cloud-service-order.jar(可执行)
你可以选择性启动任意服务:
bash
java -jar spring-cloud-gateway.jar
java -jar spring-cloud-service-user.jar
java -jar spring-cloud-service-order.jar
3、汇总

4、误区
代码形式都是 Maven 聚合父工程,语法没有任何特殊新标签!
不存在 Maven 有两套语法;区别不在 Maven 语法,在于模块职责划分、依赖引入、运行设计。
也就是说:
把一个普通多模块项目,新增多个带启动类的子模块、引入 Nacos、加上服务注解,它就变成微服务聚合工程。