Gradle 统一管理依赖

embedded/2024/10/18 5:58:26/

BOM 介绍

BOM 是 Bill of Material 的简写,表示物料清单。BOM 使我们在使用 Maven 或 Gradle 构建项目时对于依赖版本的统一变得更加规范,升级依赖版本更容易。

比如我们使用 SpringBoot 和 SpringCloud 做项目时,可以使用他们发布的 BOM

  • spring-boot-dependencies
  • spring-cloud-dependencies

使用 Gradle 发布 BOM

在公司的大型项目中,可能对于依赖的版本需要有一个统一的管理,确保所有的项目的依赖都是一致的。

当需要升级某个依赖版本时,只需要更改 BOM 项目的版本并给发布一个新版本的 BOM 项目,然后在其他项目中引入这个新版本的 BOM 即可。

既然 BOM 这么便利,Gradle 没有理由不提供一个发布 BOM 的功能,Gradle 中的这个功能由插件 java-platform 实现。

官网关于插件的使用方式:https://docs.gradle.org/7.6.2/userguide/java_platform_plugin.html

建立 Gradle 项目的过程就省略了,可以看我其他的文章,此处假定已建立好一个项目,名字叫做:test-bom

修改项目目录下的 build.gradle,使用以下代码引入插件:

plugins {id "java-platform"
}

很简单,引入这个插件之后只需要在 dependencies 下面的 constraints 中使用 api 方法引入任意喜欢的版本的依赖即可:

dependencies {constraints {// 比如此处我引入了 commons-lang3 的 jarapi("org.apache.commons:commons-lang3:3.12.0")// 其他的直接向下添加即可}
}

此处多出来一层 constraints。如果没有 constraints 的话,引用此 BOM 的项目,会自动引入 org.apache.commons:commons-lang3:3.12.0,即使没有使用 implementation 方法引入,这里涉及到 api 方法的其他方面,详见:Gradle几种引入依赖的方式介绍。

到这里这个 BOM 项目就好了。但是还有一个问题,我这个 BOM 如何给别人使用?和其他基础 库一样使用 maven-publish 插件。

首先引入 maven-publish 插件:

plugins {id "maven-publish"
}

接着定义 publish 的内容:

publishing {publications {testPlatform(MavenPublication) {from components.javaPlatform}}repositories {maven {url = "远程仓库地址"// 如果远程仓库是 https 的则不需要下面这句话,http 的需要// allowInsecureProtocol truecredentials {username = '远程仓库用户'password = '远程仓库密码'}}}
}

因为 jar 都是需要 groupId 和 artifactId 和版本的,而 artifactId 在 settings.gradle 中由 rootProject.name 定义,所以还需要在 build.gradle 中定义 groupId 和 version:

group = "com.test"
version = "1.0.0"

到目前为止,完整的 build.gradle 文件内容如下:

plugins {id "java-platform"id "maven-publish"
}group = "com.test"
version = "1.0.0"dependencies {constraints {// 比如此处我引入了 commons-lang3 的 jarapi("org.apache.commons:commons-lang3:3.12.0")// 其他的直接向下添加即可}
}publishing {publications {testPlatform(MavenPublication) {from components.javaPlatform}}repositories {maven {url = "远程仓库地址"// 如果远程仓库是 https 的则不需要下面这句话,http 的需要// allowInsecureProtocol truecredentials {username = '远程仓库用户'password = '远程仓库密码'}}}
}

在项目根目录下执行:

# Windows 使用 gradlew.bat 文件
./gradlew clean publishToMavenLocal

之后查看 $M2_HOME/repository/com/test/test-bom/1.0.0,有两个文件就表示成功了:

在这里插入图片描述

使用发布的 BOM

使用 BOM 有两种方式,Gradle 自带的 platform 方法,和 SpringBoot 的插件,叫做 io.spring.dependency-management。这两种方式看个人喜好使用。

Gradle API
api platform("com.test:test-bom:1.0.0")
Springboot 插件

插件稍微复杂些,先引入插件:

buildscripts {repositories {mavenCentral()}dependencies {// 非官方插件,需要引入 SpringBoot 插件库classpath("org.springframework.boot:spring-boot-gradle-plugin:2.7.18")}
}apply plugin: "java"
apply plugin: "io.spring.dependency-management"

然后在 dependencyManagement 引入 BOM 即可:

dependencyManagement {imports {mavenBom "com.test:test-bom:1.0.0"}
}

通过上面两种方式之一引入 BOM 之后,引入BOM 中存在的依赖就不用添加 version 了,如:

// 会自动引入 3.12.0 版本
implementation("org.apache.commons:commons-lang3")

到这里基本功能介绍完了。


那么问题来了,我如果在一个 SpringBoot 项目中使用了 SpringBoot 的依赖和我自定义的依赖,我还要写多个引入吗?

buildscripts dependencies 里面用 classpath 声明的第三方插件仓库也要自己指定版本吗?

buildscripts {dependencies {classpath("org.springframework.boot:spring-boot-gradle-plugin:2.7.18")}
}imports {mavenBom "springboot 的"mavenBom "springcloud 的"mavenBom "我自己的"
}

太难受了,我就想引入我自己的 BOM,并同时可以直接使用 SpringBoot 和 SpringCloud 的 BOM,这个可以搞。

改造 BOM 项目,添加:

javaPlatform {allowDependencies()
}dependencies {constraints {// xxx// 支持 classpath的api("org.springframework.boot:spring-boot-gradle-plugin:2.7.18")}api platform("org.springframework.boot:spring-boot-dependencies:2.7.18")api platform("org.springframework.cloud:spring-cloud-dependencies:2021.0.8")
}

必须注意:不要写到 constraints 里面。

这样重新 publishToMavenLocal 就行了。

打包完成后,buildscripts 的引入方式需要修改一下:

buildscripts {dependencies {classpath platform("com.test:test-bom:1.0.0")classpath("org.springframework.boot:spring-boot-gradle-plugin")}
}

到这里,一个 BOM 支配所有依赖版本的项目就完成了,再也不怕依赖升级和维护了。


最后贴一下 BOM 和使用 BOM 的 build.gradle 的完整内容:

// bom build.gradle
plugins {id "java-platform"id "maven-publish"
}group = "com.test"
version = "1.0.0"javaPlatform {allowDependencies()
}dependencies {constraints {// 比如此处我引入了 commons-lang3 的 jarapi("org.apache.commons:commons-lang3:3.12.0")// 其他的直接向下添加即可// 支持 classpath的api("org.springframework.boot:spring-boot-gradle-plugin:2.7.18")}api platform("org.springframework.boot:spring-boot-dependencies:2.7.18")api platform("org.springframework.cloud:spring-cloud-dependencies:2021.0.8")}publishing {publications {testPlatform(MavenPublication) {from components.javaPlatform}}repositories {maven {url = "远程仓库地址"// 如果远程仓库是 https 的则不需要下面这句话,http 的需要// allowInsecureProtocol truecredentials {username = '远程仓库用户'password = '远程仓库密码'}}}
}
// 使用 BOM 的 build.gradle
buildscript {repositories {mavenCentral()}dependencies {classpath platform("com.test:test-bom:1.0.0")classpath("org.springframework.boot:spring-boot-gradle-plugin")}
}apply plugin: "java"
apply plugin: "org.springframework.boot"group = "com.test.web"
version = "1.0"sourceCompatibility = JavaVersion.VERSION_18
targetCompatibility = JavaVersion.VERSION_18repositories {mavenCentral()
}dependencies {implementation platform("com.test:test-bom:1.0.0")// spring bootimplementation("org.springframework.boot:spring-boot-starter-web")
}

http://www.ppmy.cn/embedded/88968.html

相关文章

52、PHP 实现选择排序

题目&#xff1a; PHP 实现选择排序 描述&#xff1a; 先取一个小于n的整数d1作为第一个增量&#xff0c;把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序&#xff1b;然后&#xff0c;取第二个增量d2<d1重复上述的分组…

深入探究 Vue.js 高级技术:从响应式系统到高效组件设计的实战指南

这里有一些实用的 Vue.js 高级示例&#xff0c;涵盖了前面提到的高级知识点&#xff0c;适合在实际项目中应用&#xff1a; 1. 自定义响应式数据 使用 Vue 3 的 customRef API 创建一个自定义的响应式输入框&#xff0c;带有防抖功能。 import { customRef } from vue;funct…

使用Pandas将数据写入同一个Excel的不同sheet中

在使用 pandas 库处理 Excel 文件时&#xff0c;需要将数据写入到同一个 Excel 文件中的不同工作表&#xff08;sheet&#xff09;中。pandas 提供了一个方便的方法通过 ExcelWriter 对象来实现这一点。以下是一个示例&#xff0c;展示了如何使用 pandas 将数据写入到不同的 sh…

转世重生之当程序员从零开始,不可错过的Jupyter Notebook的详细安装教程 ♪(^∇^*)

一、前期准备工作 &#x1f609; Jupyter Notebook是基于Python的&#xff0c;因此首先需要确保您的计算机上安装了Python。建议安装Python 3.7或更高版本。Python下载网站链接&#xff1a;Python。 pip是Python的包管理工具&#xff0c;用于安装和管理Python包。在大多数情况下…

秒懂Linux之编写小程序——进度条

目录 一.前文摘要 二.进度条编写 三全部代码&#xff08;非Linux环境下测试&#xff09; 一.前文摘要 在开始编写之前我们先来学习一些后面会用到的知识点~ 测试结果发现&#xff0c;Sleep无作用&#xff0c;编译完会立刻打印~ 再来看另一个测试~我们同样没有换行&#xff0c…

【gpt预测与推理区别】

推理时不能并行计算所有位置的主要原因在于生成文本的过程是自回归的&#xff0c;也就是说&#xff0c;生成每个新的单词都依赖于之前已经生成的单词。这个过程需要一步一步地进行&#xff0c;因为每一步的输出会成为下一步的输入。下面是对这个过程的详细解释&#xff1a; 自…

面试经典 222. 完全二叉树的节点个数

二叉树我最近刷的特别多&#xff0c;差不多快刷完了&#xff0c;但是有一种题型差点给我忽略了&#xff0c;那就是完全二叉树&#xff0c;这也是一个很重要的题型&#xff0c;今天刚好有一道题目可以来复习一下完全二叉树的特性 题目链接如下&#xff1a;https://leetcode.cn/…

笑谈“八股文”,人生不成文

一、“八股文”在实际工作中是助力、阻力还是空谈&#xff1f; 作为现在各类大中小企业面试程序员时的必问内容&#xff0c;“八股文”似乎是很重要的存在。但“八股文”是否能在实际工作中发挥它“敲门砖”应有的作用呢&#xff1f;有IT人士不禁发出疑问&#xff1a;程序员面试…