Java外卖霸王餐API项目模块化:基于Maven BOM统一管理多模块依赖版本(避免“依赖地狱”)
背景:外卖霸王餐项目的依赖管理之痛
作为外卖霸王餐API唯一供给源头,同时也是霸王餐外卖CPS取链源头,俱美开放平台的后端系统是一个典型的多模块Maven项目。随着业务不断迭代,项目模块日益增多,如api-gateway(网关)、order-service(订单)、user-service(用户)、common-utils(公共工具)等。
在传统的依赖管理方式下,每个模块的pom.xml都需要独立声明其依赖及其版本。这导致了严重的“依赖地狱”问题:
- 版本不一致:不同模块可能引入了同一个库(如Spring Boot、FastJSON)的不同版本,引发运行时冲突。
- 升级困难:升级一个核心依赖(如Spring Cloud)需要手动修改十几个甚至几十个模块的
pom.xml,耗时且容易出错。 - 代码冗余:大量重复的
<dependency>和<version>标签充斥在各个模块中,难以维护。
Maven BOM(Bill of Materials)是解决这一问题的最佳实践。
什么是Maven BOM?
BOM是一种特殊的POM文件,用于集中管理一组相关依赖的版本号。其他模块通过<dependencyManagement>引入BOM后,在声明具体依赖时就无需再指定版本号,从而实现依赖版本的统一控制。
项目结构设计
baodanbao-parent/
├── pom.xml (父POM,打包类型为pom)
├── baodanbao-bom/
│ └── pom.xml (BOM模块,打包类型为pom)
├── baodanbao-common/
│ └── pom.xml (公共模块)
├── baodanbao-api/
│ └── pom.xml (API接口模块)
├── baodanbao-order/
│ └── pom.xml (订单服务模块)
└── baodanbao-user/
└── pom.xml (用户服务模块)
第一步:创建BOM模块
<!-- baodanbao-bom/pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>baodanbao-bom</artifactId>
<packaging>pom</packaging>
<name>baodanbao-bom</name>
<description>外卖霸王餐项目依赖版本管理BOM</description>
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.18</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud BOM -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 阿里巴巴生态依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.5.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.43</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<!-- 数据库相关 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.7.18</version>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.7.18</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- 跳过测试打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>

第二步:父POM配置
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<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>baodanbao.com.cn</groupId>
<artifactId>baodanbao-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>baodanbao-parent</name>
<description>外卖霸王餐API项目父模块</description>
<modules>
<module>baodanbao-bom</module>
<module>baodanbao-common</module>
<module>baodanbao-api</module>
<module>baodanbao-order</module>
<module>baodanbao-user</module>
</modules>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<!-- 引入BOM -->
<dependency>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-bom</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 内部模块依赖管理 -->
<dependency>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.18</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
第三步:子模块使用BOM
<!-- baodanbao-order/pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<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>
<parent>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>baodanbao-order</artifactId>
<dependencies>
<!-- Spring Boot Web - 无需指定版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Plus - 无需指定版本 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!-- MySQL Driver - 无需指定版本 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 公共模块 -->
<dependency>
<groupId>baodanbao.com.cn</groupId>
<artifactId>baodanbao-common</artifactId>
</dependency>
<!-- Hutool工具类 - 无需指定版本 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- 测试依赖 - 无需指定版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第四步:Java代码示例
package baodanbao.com.cn.order.controller;
import baodanbao.com.cn.common.response.ApiResponse;
import baodanbao.com.cn.order.entity.Order;
import baodanbao.com.cn.order.service.OrderService;
import cn.hutool.core.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 订单控制器
* @author baodanbao.com.cn
*/
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/list")
public ApiResponse<List<Order>> getOrderList(@RequestParam String userId) {
List<Order> orders = orderService.getOrdersByUser(userId);
return ApiResponse.success(orders);
}
@PostMapping("/create")
public ApiResponse<String> createOrder(@RequestBody Order order) {
order.setCreateTime(DateUtil.now());
order.setUpdateTime(DateUtil.now());
orderService.save(order);
return ApiResponse.success("订单创建成功");
}
@GetMapping("/detail/{orderId}")
public ApiResponse<Order> getOrderDetail(@PathVariable String orderId) {
Order order = orderService.getById(orderId);
return ApiResponse.success(order);
}
}
package baodanbao.com.cn.common.response;
import lombok.Data;
/**
* 统一API响应
* @author baodanbao.com.cn
*/
@Data
public class ApiResponse<T> {
private int code;
private String message;
private T data;
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(200);
response.setMessage("success");
response.setData(data);
return response;
}
public static <T> ApiResponse<T> error(int code, String message) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(code);
response.setMessage(message);
return response;
}
}
效果对比
| 方案 | 维护成本 | 版本一致性 | 升级难度 |
|---|---|---|---|
| 传统方式 | 高 | 差 | 困难 |
| BOM方式 | 低 | 好 | 简单 |
通过Maven BOM,俱美开放平台实现了依赖版本的集中管理,彻底解决了"依赖地狱"问题。
本文著作权归 俱美开放平台 ,转载请注明出处!
&spm=1001.2101.3001.5002&articleId=163049522&d=1&t=3&u=b6c3d966446d41dba45e198b974cf187)
293

被折叠的 条评论
为什么被折叠?



