当前位置: 首页 > news >正文

告别“复制粘贴”!微服务架构下如何统一管理POM依赖版本(实战详解)

一.先说一个场景?

很多从单体应用转型微服务的同学都会遇到这样一个尴尬的场景:

刚开始拆分单体项目时,每新建一个微服务(比如把单体项目的菜单功能单独拆成menu-service微服务),都要去原来的单体项目里翻pom.xml,把Spring Boot、MyBatis、MySQL等依赖的版本号一个个复制过来。

不仅麻烦,而且一旦要升级版本(比如Spring Boot从2.7升到3.0),你得去几十个微服务里逐个修改版本号,简直是“灾难现场”。


其实,成熟的微服务架构早就解决了这个问题。今天我们就来聊聊,如何通过“统一父工程 + BOM模式”,彻底解放双手,实现依赖版本的“中央集权”

思考:什么是BOM?

BOM 是Bill of Materials(物料清单)的缩写,在微服务架构中,它指代一份特殊的 Maven POM 文件。这份文件充当了依赖版本的“中央集权”角色,通过<dependencyManagement>集中定义了所有第三方库的统一版本号。引入 BOM 后,各个微服务模块在声明依赖时无需再指定版本号,从而确保了整个系统依赖版本的一致性,有效避免了版本冲突,并极大地简化了后续的升级与维护工作。

二.核心思路:建立“依赖联邦”

不要让你的微服务直接继承Spring Boot的官方Parent,而是继承你们项目组自定义的Parent。

这个自定义Parent负责统一管理所有依赖的版本。微服务只需要“听话”继承它,就能自动获得所有标准依赖版本,无需自己维护。

三.实战演示

1.创建一个专门的“版本管理工程”(BOM项目)

首先,创建一个空的Maven项目,不包含任何Java代码,只包含一个pom.xml。我们称之为myproject-bom。

它的作用是:定义所有微服务需要用到的第三方库版本(如MySQL, Redis, Hutool等)以及Spring Cloud组件的版本。

①定义BOM项目自身的坐标

<!-- 1.定义BOM项目自身的坐标--> <groupId>com.casually</groupId> <artifactId>myproject_bom</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging><!--pom就表明该项目只是依赖版本清单,即BOM项目,本身不会打jar、war包-->

②添加说明信息(这个不写也没事,但是为了提高可读性)

<!-- 2.添加说明信息(这个不写也没事,但是为了提高可读性)--> <name>myproject_bom</name> <description>这是微服务项目的BOM项目(即:依赖清单,统一管理所有依赖的版本)</description>

③依赖版本号变量定义(更加灵活,拒绝硬编码)

注意:像spring-boot.version这种变量名,是自定义的变量名,你自己知道是啥意思就行,写成123.version也行
<!-- 3.依赖版本号变量定义(拒绝硬编码)--> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <java.version>17</java.version> <!-- Spring Boot Version --> <spring-boot.version>3.3.3</spring-boot.version> <!-- Third Party Dependencies Version --> <mysql.version>8.0.28</mysql.version> <mybatis-spring-boot.version>3.0.3</mybatis-spring-boot.version> <pagehelper.version>1.4.6</pagehelper.version> <aliyun-oss.version>3.17.4</aliyun-oss.version> <jaxb.version>2.3.3</jaxb.version> <spring-security.version>3.1.5</spring-security.version> <spring-mail.version>3.1.5</spring-mail.version> <spring-data-redis.version>3.2.7</spring-data-redis.version> <jjwt.version>0.9.1</jjwt.version> <pdfbox.version>2.0.24</pdfbox.version> <langchain4j.version>1.0.1-beta6</langchain4j.version> <fastjson.version>2.0.38</fastjson.version> <nacos.version>2023.0.1.0</nacos.version> <!-- Plugin Version --> <maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version> </properties>

④核心配置:<dependencyManagement>

这是 BOM 的核心。

注意:这里只声明依赖,不引入依赖。

说白了就是:我(父工程)手里有所有的版本号(定标准),但我手里没有 jar 包(不占内存)。你们(子模块)谁想要,就自己伸手拿,拿了就是标准版,不用问版本是多少。


相当于一本书的书单,子项目要是需要某个依赖,直接引入就行,也不用写版本号,因为这里就给规定好了,哪个依赖是哪个版本。

<!-- 4.核心配置:<dependencyManagement>--> <dependencyManagement> <dependencies> <!-- Spring Boot BOM (作为基础,这个在单体项目中不存在,属于是BOM项目的特色了) --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version><!--这就用到了上一步定义的依赖变量--> <type>pom</type> <scope>import</scope> </dependency> <!-- 然后把单体项目的依赖,一个一个地弄进来就行了--> <!-- Web开发--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <!-- 请使用最新稳定版 --> <scope>compile</scope> <!-- 或 optional --> </dependency> <!-- 测试 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot.version}</version> <scope>test</scope> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- MyBatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis-spring-boot.version}</version> </dependency> <!-- 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>${pagehelper.version}</version> </dependency> <!-- 阿里云 OSS --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>${aliyun-oss.version}</version> </dependency> <!-- JAXB (Java 17 需要) --> <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>${jaxb-runtime}</version> </dependency> <!-- Spring Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>${spring-security.version}</version> </dependency> <!-- Spring Mail --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>${spring-mail.version}</version> </dependency> <!-- Spring Data Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>${spring-data-redis.version}</version> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>${jjwt.version}</version> </dependency> <!-- PDFBox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>${pdfbox.version}</version> </dependency> <!-- LangChain4j (AI) --> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId> <version>${langchain4j.version}</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-spring-boot-starter</artifactId> <version>${langchain4j.version}</version> </dependency> <!-- Fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- Nacos --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${nacos.version}</version> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${nacos.version}</version> </dependency> </dependencies> </dependencyManagement>

统一编译工具和打包工具的版本及配置标准,一劳永逸

<!-- 5.统一编译工具和打包工具的版本及配置标准,一劳永逸--> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> </plugin> </plugins> </pluginManagement> </build>

2.将bom项目install(安装)到本地

3.在微服务项目中使用(以菜单服务menu-service为例)

注意:前提是两个项目必须使用同一个maven仓库,不然这不是纯扯淡吗,根本不可能找到。

<!-- 1.导入BOM项目(不添加依赖,而是导入版本信息)--> <dependencyManagement> <dependencies> <dependency> <groupId>com.casually</groupId> <artifactId>myproject_bom</artifactId> <version>1.0-SNAPSHOT</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- ----------------------------------------------- --> <!-- 2.导入其他所需的依赖(但是不用声明版本了,因为1中已经规定好了)--> <dependencies> <!-- Web依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies>

好处:设置了BOM项目以后,微服务项目引入依赖时再也不用写版本号了,因为BOM已经事先规定好了

注意:不要把具体的依赖,放进<dependencyManagement>标签中,不然依赖只被声明,但并不会导入

四.这样做的好处

  • 开发效率极高

创建新微服务时,你只需要复制一份标准的pom.xml模板,修改artifactId即可。所有依赖版本自动对齐,不需要去查单体项目用了什么版本。

  • 版本一致性(防冲突)

所有微服务(用户服务、订单服务、菜单服务)都强制使用同一套依赖版本。彻底杜绝了“服务A用Jackson 2.11,服务B用Jackson 2.13”导致的序列化报错。

  • 一键升级

如果Spring Boot出了安全漏洞需要升级,你只需要修改myproject-bom里的 $ {spring-boot.version}变量,然后重新发布BOM。所有微服务只需要更新父版本号,即可全部完成升级。


针对你当前情况的建议

既然你已经有了单体项目,想拆分微服务,建议按以下路径操作:

提取
打开你单体项目的pom.xml,把里面用到的所有<version>提取出来,放到一个新的myproject-bom工程的<properties>中。

发布
执行mvn install,把这个myproject-bom安装到你本地的Maven仓库(或者公司的Nexus/Artifactory私服)。

新建
创建menu-service,在pom.xml中<parent>指向myproject-bom(或者继承它的父工程)。

清洗
在menu-service的pom.xml中,大胆删除所有依赖的<version>标签。

这样,你就从“手工管理依赖”进化到了“工程化管理依赖”。

http://www.cnnetsun.cn/news/2095268.html

相关文章:

  • ARM RealView Debugger多核同步调试技术详解
  • 基于RAG框架构建企业知识库:从原理到生产级实践
  • 【国家级智慧农业项目内部文档】:VSCode+CMake+STM32F4构建边缘端作物监测系统的9个避坑要点
  • ARIMA模型时间序列预测区间实现与解析
  • GoWxDump:免费微信取证分析工具的终极指南与使用教程
  • Qianfan-OCR数据结构优化:提升大批量图片处理效率的编程技巧
  • Youtu-VL-4B-Instruct WebUI使用手册:5类高频问题(描述/OCR/检测/场景/代码)标准提问模板
  • Phi-3-mini-128k-instruct惊艳效果展示:128K上下文下多轮复杂推理对话实录
  • SharpKeys:Windows键盘重映射的专业深度优化解决方案
  • Windows Cleaner终极指南:3步解决C盘爆红,让旧电脑重获新生!
  • 零样本视觉模型编排框架Overeasy:快速构建定制化AI视觉流水线
  • M2FP人体解析零基础教程:5分钟搭建WebUI服务,一键识别身体部位
  • 比特币挖矿硬件投资决策:深度学习模型MineROI-Net解析
  • 量子计算基础:Hadamard门与CNOT门的原理与应用
  • 用Markdown驱动设计:提升团队协作效率的工程化实践
  • Python描述性统计分析在机器学习数据预处理中的应用
  • 千问 LeetCode 1862题的Python代码怎么写?
  • 千问 LeetCode 1866.恰有 K 根木棍可以看到的排列数目 public int rearrangeSticks(int n, int k)
  • K8s 节点间网络通信调优
  • 煌上煌2025年净利润大增102.32% 2026年一季度开局稳健
  • ESP USB Bridge:多功能嵌入式调试工具实战指南
  • 从单体智能到群体协作:AgentMesh架构思想与实战指南
  • 上下文工程:让Agent真正用好记忆与知识
  • Display Driver Uninstaller 完全手册:显卡驱动清理终极方案
  • Optional类详解
  • JD-GUI插件开发终极指南:7步构建高效Java反编译扩展
  • Phi-3.5-mini-instruct部署教程:CSDN GPU平台一键启动,7860端口访问全流程
  • 多模型机器学习:原理、技术与实战应用
  • 自编码器在回归任务中的特征提取实践
  • VideoGet(视频下载工具)