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

SpringBoot开发——Maven多模块工程最佳实践及详细示例

文章目录

  • 一、前言
  • 二、Maven多模块工程的最佳实践
    • 1、项目结构清晰
    • 2、依赖管理统一
    • 3、插件配置统一
    • 4、版本控制一致
    • 5、模块间通信简化
  • 三、详细示例
    • 1、项目结构
    • 2、父模块(parent)的pom.xml文件
    • 3、子模块(module-api)的pom.xml文件
    • 4、模块间依赖示例
  • 四、关于${project.version}

一、前言

在大型软件开发项目中,项目模块的划分和管理至关重要。Maven多模块项目架构是一种高效的项目组织方式,通过将项目划分为多个模块,每个模块负责一个特定的功能,可以提高项目的可维护性和可扩展性。本文将详细介绍Maven多模块工程组织的最佳实践,并给出一个详细示例。

二、Maven多模块工程的最佳实践

1、项目结构清晰

  • 项目应该按照功能、业务或技术划分模块,每个模块应该有明确的职责和边界,避免功能交叉或耦合过度。
  • 项目根目录下通常包含一个父模块(parent),管理整个项目的构建、依赖和版本控制,以及多个子模块(module),每个子模块负责一个具体的功能。

2、依赖管理统一

  • 在父模块的pom.xml文件中,通过<dependencyManagement>标签统一声明所有子模块需要的依赖及其版本号,子模块通过继承父模块来简化依赖配置。
  • 子模块可以通过<dependencies>标签添加自己特有的依赖,无需重复声明版本号。

3、插件配置统一

  • 父模块统一管理构建插件及其配置,确保所有子模块使用相同的构建流程。
  • 子模块可以根据需要添加额外的插件或覆盖父模块的插件配置。

4、版本控制一致

  • 父模块中定义项目的全局版本号,子模块继承父模块的版本号,确保整个项目的一致性。
  • 通过<properties>标签定义项目属性,如Java版本Spring版本等,子模块可以直接引用这些属性。

5、模块间通信简化

  • 使用Maven的模块间依赖机制,子模块可以直接引用其他子模块的代码和资源,简化模块间的通信和协作。
  • 通过合理定义和使用模块间的依赖关系,确保模块间的正确交互和协作。

三、详细示例

假设我们有一个多模块项目,包含以下模块:

  • parent(父模块)
  • module-api(API模块)
  • module-service(服务模块)
  • module-web(Web模块)

1、项目结构

项目结构如下:

my-multimodule-project/
|-- parent/
|   |-- pom.xml
|-- module-api/
|   |-- pom.xml
|-- module-service/
|   |-- pom.xml
|-- module-web/|-- pom.xml

2、父模块(parent)的pom.xml文件

  • 在父模块的pom.xml文件中,定义groupIdartifactIdversion
  • 使用<packaging>pom</packaging>来指定这是一个聚合项目(即多模块项目)。
  • <modules>标签中列出所有子模块。
<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>my-multimodule-project</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging><modules><module>module-api</module><module>module-service</module><module>module-web</module></modules><properties><java.version>1.8</java.version><spring.version>5.3.10</spring.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><!-- 其他依赖 --></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${java.version}</source><target>${java.version}</target></configuration></plugin><!-- 其他插件 --></plugins></build>
</project>

3、子模块(module-api)的pom.xml文件

  • 在每个子模块的pom.xml文件中,使用<parent>标签来指定父模块。
  • <parent>标签中,不需要重复定义groupIdversion,因为Maven会自动从父模块中继承这些值。
  • 只需要指定父模块的groupIdartifactIdrelativePath(如果父模块不在默认位置)。
<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><artifactId>module-api</artifactId><packaging>jar</packaging><parent><groupId>com.example</groupId><artifactId>my-multimodule-project</artifactId><version>1.0-SNAPSHOT</version><!-- 如果父模块不在默认位置,可以指定relativePath -->  <!-- <relativePath>../parent/pom.xml</relativePath> -->  </parent><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency><!-- 其他依赖 --></dependencies>
</project>

4、模块间依赖示例

假设module-service模块依赖于module-api模块,可以在module-servicepom.xml文件中添加以下依赖:

<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>com.example</groupId>  <artifactId>my-multimodule-project</artifactId>  <version>1.0-SNAPSHOT</version>  <!-- 如果父模块不在默认位置,可以指定relativePath -->  <!-- <relativePath>../parent/pom.xml</relativePath> -->  </parent>  <artifactId>module-service</artifactId>  <packaging>jar</packaging>  <!-- 子模块特有的配置,如依赖、插件等 -->  <dependencies>  <dependency>  <groupId>com.example</groupId>  <artifactId>module-api</artifactId>  <version>${project.version}</version> <!-- 使用${project.version}来引用父模块的version -->  </dependency>  <!-- 这里可以添加其他依赖 -->  </dependencies>  
</project>

在上面的示例中,module-apimodule-service子模块都通过<parent>标签继承了父模块my-multimodule-projectgroupIdversion。这样,你就不需要在每个子模块中重复这些值了。通过上述配置,我们实现了一个清晰、可维护的Maven多模块项目结构。每个模块都有明确的职责和边界,依赖关系通过父模块统一管理,插件配置和版本控制也保持一致。这种项目组织方式有助于提高开发效率,降低维护成本,并方便后续扩展和升级。

四、关于${project.version}

Maven项目中,${project.version} 是一个内置的Maven属性,它代表了当前项目的版本号。这个属性是在Maven解析pom.xml文件时自动设置的,因此你不需要手动定义它。

当你使用${project.version}时,Maven会用当前项目的版本号来替换这个占位符。这个版本号通常是在项目的pom.xml文件的<version>标签中定义的。

在多模块项目中,如果子模块通过<parent>标签继承了父模块的版本号,那么子模块中的${project.version}将会解析为父模块中定义的版本号(前提是子模块没有覆盖这个版本号)。这是因为Maven在解析子模块的pom.xml时,会首先解析父模块的pom.xml,并将父模块中的信息(包括版本号)传递给子模块。

举个例子,如果你有一个父模块parent-pom,它的版本号是1.0.0,并且有一个子模块child-module,子模块的pom.xml中通过<parent>标签继承了父模块的版本号,那么在子模块的pom.xml中使用${project.version}时,它会被解析为1.0.0。

需要注意的是,虽然${project.version}在大多数情况下都很有用,但在某些情况下(比如父模块和子模块需要不同的版本号时),你可能需要在子模块中显式地定义版本号,而不是使用继承的版本号。此外,如果你在一个模块中引用了另一个模块作为依赖,并且希望确保它们使用相同的版本号,那么使用${project.version}是一个很好的做法,因为它可以确保版本的一致性。

相关文章:

SpringBoot开发——Maven多模块工程最佳实践及详细示例

文章目录 一、前言二、Maven多模块工程的最佳实践1、项目结构清晰2、依赖管理统一3、插件配置统一4、版本控制一致5、模块间通信简化 三、详细示例1、项目结构2、父模块&#xff08;parent&#xff09;的pom.xml文件3、子模块&#xff08;module-api&#xff09;的pom.xml文件4…...

C 语言面向对象

面向对象的基本特性&#xff1a;封装&#xff0c;继承&#xff0c;多态 1.0 面向过程概念 当我们在编写程序时&#xff0c;通常采用以下步骤&#xff1a; 1. 将问题的解法分解成若干步骤 2. 使用函数分别实现这些步骤 3. 依次调用这些函数 这种编程风格的被称作 面向过程…...

无人机探测:光电侦测核心技术算法详解!

核心技术 双光谱探测跟踪&#xff1a; 可见光成像技术&#xff1a;利用无人机表面反射的自然光或主动光源照射下的反射光&#xff0c;通过高灵敏度相机捕捉图像。该技术适用于日间晴朗天气下的无人机探测&#xff0c;具有直观、易于识别目标的特点。 红外成像技术&#xff1…...

ffmpeg视频滤镜:替换部分帧-freezeframes

滤镜描述 freezeframes 官网地址 > FFmpeg Filters Documentation 这个滤镜接收两个输入&#xff0c;然后会将第一个视频中的部分帧替换为第二个视频的某一帧。 滤镜使用 参数 freezeframes AVOptions:first <int64> ..FV....... set first fra…...

PHP 超级全局变量

超级全局变量是指在php任意脚本下都可以使用 PHP 超级全局变量列表: $GLOBALS&#xff1a;是PHP的一个超级全局变量组&#xff0c;在一个PHP脚本的全部作用域中都可以访问。 $_SERVER&#xff1a;$_SERVER 是一个PHP内置的超级全局变量,它是一个包含了诸如头信息(header)、路…...

Pytorch使用手册-Tensors(专题二)

这段代码是对 PyTorch 中张量(Tensors)的详细介绍和操作演示。以下是逐步讲解: 1. 什么是张量 (Tensor) 张量是一种专门的数据结构,与 NumPy 的多维数组(ndarray)类似: 它可以在 GPU 或其他硬件加速器上运行。张量可以与 NumPy 共享内存,避免不必要的数据拷贝。它是为…...

centos安装小火车

平时没事闲着 装个小火车玩-------->>>>> yum install sl.x86_64 启动命令 sl 就会出现以下场景...

241125学习日志——[CSDIY] [InternStudio] 大模型训练营 [17]

CSDIY&#xff1a;这是一个非科班学生的努力之路&#xff0c;从今天开始这个系列会长期更新&#xff0c;&#xff08;最好做到日更&#xff09;&#xff0c;我会慢慢把自己目前对CS的努力逐一上传&#xff0c;帮助那些和我一样有着梦想的玩家取得胜利&#xff01;&#xff01;&…...

sklearn中常用数据集简介

scikit-learn库中提供了包括分类、回归、聚类、降维等多种机器学习任务所需的常用数据集&#xff0c;方便进行实验和研究&#xff0c;它们主要被封装在sklearn.datasets中&#xff0c;本文对其中一些常用的数据集进行简单的介绍。 1.Iris&#xff08;鸢尾花&#xff09;数据集…...

机器学习在教育方面的应用文献综述

引言 随着大数据时代的到来&#xff0c;机器学习作为人工智能的一个重要分支&#xff0c;在教育领域展现出广泛的应用前景。本文综述了机器学习技术在教育领域的应用&#xff0c;包括个性化学习、智能评估、知识图谱构建等多个方面。 个性化学习 个性化学习是机器学习…...

滑动窗口最大值(java)

题目描述 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1&#xff1a; 输入&#xff1a;nums [1,3,-1,-3,5,3,6,7]…...

sklearn学习

介绍&#xff1a;scaler&#xff1a;换算的意思 1. 归一化MinMaxScaler() 归一化的意思是将一堆数&#xff0c;如果比较离散&#xff0c;为了让数据更适合模型训练&#xff0c;将离散的数据压缩到0到1之间&#xff0c;以方便模型更高效优质的学习&#xff0c;而对数据的预处理…...

Ubuntu下手动设置Nvidia显卡风扇转速

在Ubuntu下&#xff0c;您可以使用 NVIDIA显卡驱动程序提供的工具手动调整风扇转速。以下是详细步骤&#xff1a; 1. 确保已安装NVIDIA显卡驱动 确保系统已经安装了正确的NVIDIA驱动&#xff1a; nvidia-smi如果没有输出驱动信息&#xff0c;请先安装驱动&#xff1a; sudo…...

Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…...

ES 和Kibana-v2 带用户登录验证

1. 前言 ElasticSearch、可视化操作工具Kibana。如果你是Linux centos系统的话&#xff0c;下面的指令可以一路CV完成服务的部署。 2. 服务搭建 2.1. 部署ElasticSearch 拉取docker镜像 docker pull elasticsearch:7.17.21 创建挂载卷目录 mkdir /**/es-data -p mkdir /**/…...

CodeIgniter如何手动将模型连接到数据库

在CodeIgniter中&#xff0c;模型通常是自动与数据库连接的&#xff0c;因为模型类&#xff08;CI_Model&#xff09;已经内置了对数据库操作的支持。但是&#xff0c;如果你需要手动指定数据库连接或者进行一些特殊的数据库配置&#xff0c;你可以通过几种方式来实现。 1. 使…...

商用密码应用安全性评估,密评整体方案,密评管理测评要求和指南,运维文档,软件项目安全设计相关文档合集(Word原件)

一、 密码应用安全性评估方案 &#xff08;一&#xff09; 密码应用测评工作思路 1.1.1. 测评准备活动的主要任务 1.1.2. 测评准备活动的输出文档 1.2. 方案编制活动 1.2.1. 方案编制活动的主要任务 1.2.2. 方案编制活动的输出文档 1.3. 现场预评估活动 1.3.1. 现场测评…...

AI赋能电商:构建高效、智能化的新零售生态

随着人工智能&#xff08;AI&#xff09;技术的不断进步&#xff0c;其在电商领域的应用日益广泛&#xff0c;从购物推荐到供应链管理&#xff0c;再到商品定价&#xff0c;AI正在全面改变传统电商的运营模式&#xff0c;并推动行业向智能化和精细化方向发展。本文将探讨如何利…...

【GAMES101笔记速查——Lecture 19 Cameras,Lenses and Light Fields】

本章节内容&#xff1a;相机、棱镜、光场 计算机图形学的两种成像方法&#xff1a; 1.合成方法&#xff1a;光栅化、光线追踪&#xff08;展示出现实没有的东西&#xff09; 2.捕捉方法&#xff1a;相机&#xff08;捕捉现实已有的东西&#xff09; 目录 1 相机 1.1 针孔相…...

虚拟机上搭建达梦DSC简略步骤

vmware 17 centos 7.6 达梦 dm8_20240920_x86_rh7_64.iso cd /d C:\Program Files (x86)\VMware\VMware Workstation\.\vmware-vdiskmanager.exe -c -s 100MB -a lsilogic -t 2 "F:\vm\dmdsc\sharedisk\share-dcr.vmdk" .\vmware-vdiskmanager.exe -c -s 100MB -a l…...

Python和R荧光分光光度法

&#x1f335;Python片段 Python在处理荧光分光光度法数据方面非常强大&#xff0c;得益于其丰富的数据处理和可视化库&#xff0c;可以轻松实现从数据读取到分析的完整流程。荧光分光光度法用于测量物质在激发光照射下发出的荧光强度&#xff0c;常用于定量分析和特性研究。 …...

电子学习中的关键游戏化元素

游戏化彻底改变了电子学习领域&#xff0c;提供了一种使学习具有吸引力、互动性和有效性的方法。通过将类似游戏的功能集成到教育平台中&#xff0c;教育工作者可以增强动力&#xff0c;提高知识记忆&#xff0c;并创造动态的学习体验。游戏化的关键要素为设计与学习者产生共鸣…...

算法日记 33 day 动态规划(打家劫舍,股票买卖)

今天来看看动态规划的打家劫舍和买卖股票的问题。 上题目&#xff01;&#xff01;&#xff01;&#xff01; 题目&#xff1a;打家劫舍 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金…...

JavaScript的let、var、const

这张图片主要介绍了JavaScript中的三种变量声明方式&#xff1a;let、var和const。 1. let 含义&#xff1a;let是现在实际开发中常用的变量声明方式。特点&#xff1a; 块级作用域&#xff1a;let声明的变量只在其所在的块级作用域内有效。例如&#xff1a;{let x 10; } co…...

C语言-数学基础问题

一.奇数、偶数问题 1.从键盘上输入一个整数&#xff0c;判断并输出它是奇数还是偶数。 //从键盘上输入一个整数&#xff0c;判断并输出它是奇数还是偶数。 main() {int i;printf("输入一个整数:\n");scanf("%d",&i);if(i%20)printf("它是偶数\n…...

解决单元测试时找不到类名

场景&#xff1a; springboot单元测试mockito对mapper进行mock时&#xff1a; tk.mybatis.mapper.mapperexception: 无法获取实体类 XX.xx 对应的表名 分析&#xff1a; 使用了一个方法&#xff1a;Example examplenew Example(User.class); 进入源码后发现Entityhelper没…...

从零开始-VitePress 构建个人博客上传GitHub自动构建访问

从零开始-VitePress 构建个人博客上传GitHub自动构建访问 序言 VitePress 官网&#xff1a;VitePress 中文版 1. 什么是 VitePress VitePress 是一个静态站点生成器 (SSG)&#xff0c;专为构建快速、以内容为中心的站点而设计。简而言之&#xff0c;VitePress 获取用 Markdown…...

【案例学习】如何使用Minitab实现包装过程的自动化和改进

Masimo 是一家全球性的医疗技术公司&#xff0c;致力于开发和生产各种行业领先的监控技术&#xff0c;包括创新的测量、传感器和患者监护仪。在 Masimo Hospital Automation 平台的助力下&#xff0c;Masimo 的连接、自动化、远程医疗和远程监控解决方案正在改善医院内外的护理…...

【ArcGISPro】使用AI提取要素-土地分类(sentinel2)

Sentinel2数据处理 【ArcGISPro】Sentinel-2数据处理-CSDN博客 土地覆盖类型分类 处理结果...

深度解析:Nginx模块架构与工作机制的奥秘

文章目录 前言Nginx是什么?Ngnix特点&#xff1a; 一、Nginx模块与工作原理1.Nginx的模块1.1 Nginx模块常规的HTTP请求和响应的流程图:1.2 Nginx的模块从结构上分为如下三类&#xff1a;1.3 Nginx的模块从功能上分为如下三类: 2.Nginx的进程模型2.1 Nginx进程结构2.2 nginx进程…...