在实际的项目开发中,先后使用过两种的依赖版本控制,两种方式各有利弊,现在就对这两个方式做下总结,以及给出一个个人使用的方案。
目标
使用Gradle插件和BOM控制项目中的公共依赖版本
实现方式
1、自定义BOM
整体结构
xx-bom -> xx-springboot-parent -> xx-project
xx-BOM结构:
BOM也是一个简单的Gradle项目,以下是build.gradle示例,包含了依赖版本声明以及上传功能
import org.springframework.boot.gradle.plugin.SpringBootPlugin
plugins {
id "idea"
id "java-platform"
id "maven-publish"
id "org.springframework.boot" version "2.7.5"
}
repositories {
mavenLocal()
maven { url "https://maven.aliyun.com/nexus/content/groups/public/" }
mavenCentral()
}
javaToolchains {
version(17)
}
group "com.xxx.xxx"
version "0.0.1"
configurations{
javaPlatform.allowDependencies()
}
ext {
junit_bom_version = "5.8.2"
lombok_version = "1.18.20"
}
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
publishing {
repositories {
maven {
allowInsecureProtocol = true
credentials {
username "${maven_username}"
password "${maven_password}"
}
url "xxx"
}
}
publications {
maven(MavenPublication) {
groupId = "${project.group}"
artifactId = "${project.archivesBaseName}"
version = "${project.version}"
from components.javaPlatform
}
}
}
dependencies {
api(platform(SpringBootPlugin.BOM_COORDINATES))
api(platform("org.junit:junit-bom:${junit_bom_version}"))
constraints {
api("org.projectlombok:lombok:${lombok_version}")
}
}
xx-springboot-parent中主要声明了项目中会使用的springboot相关组件
xx-project为实际开发的项目,在此项目中引入xx-spingboot-parent进行依赖版本控制
build.gradle示例如下
ext {
xx_spring_boot_parent = "com.xx.xx:xx-spring-boot-parent:0.0.7"
}
dependencies {
implementation("${xx}")
}
2、自定义gradle文件
预定义一个gradle文件,在此文件中声明项目中使用的依赖版本
version.gradle示例
// 依赖版本管理
ext {
version = [
"springboot_version" : "2.7.5",
"lombok_version" : "1.18.20"
]
dependencies = [
"springboot_web_version" : "org.springframework.boot:spring-boot-starter-web:${version.springboot_version}",
"springboot_aop_version" : "org.springframework.boot:spring-boot-starter-aop:${version.springboot_version}",
"springboot_validation_version" : "org.springframework.boot:spring-boot-starter-validation:${version.springboot_version}",
"springboot_security_version" : "org.springframework.boot:spring-boot-starter-security:${version.springboot_version}",
"springboot_data_redis_version" : "org.springframework.boot:spring-boot-starter-data-redis:${version.springboot_version}",
"springboot_actuator_version" : "org.springframework.boot:spring-boot-starter-actuator:${version.springboot_version}",
"lombok_version" : "org.projectlombok:lombok:${version.lombok_version}"
]
}
build.gradle示例如下
buildscript {
String cmd = 'git config core.hooksPath githooks'
cmd.execute().text.trim()
//设置仓库
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://repo.spring.io/milestone'}
}
}
plugins {
id 'checkstyle'
}
//配置全局, 包括root项目和子项目
allprojects {
group 'com.xx'
version '1.0-SNAPSHOT'
//配置编码格式
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
//设置仓库
repositories {
maven { url "https://maven.aliyun.com/nexus/content/groups/public/" }
mavenLocal()
mavenCentral()
maven {
allowInsecureProtocol = true
url "xxx"
}
}
}
apply from: 'version.gradle'
//配置所有子项目
subprojects {
apply plugin: 'java'
apply plugin: 'java-library' //api
apply plugin: 'io.spring.dependency-management'
apply plugin: 'checkstyle'
group 'com.xxx'
version '1.0-SNAPSHOT'
sourceCompatibility= JavaVersion.VERSION_17
targetCompatibility= JavaVersion.VERSION_17
// dependencyManagement版本统一管理,类似于父maven的dependencyManagement
dependencyManagement {
dependencies {
for(depJar in rootProject.ext.dependencies){
dependency depJar.value
}
}
}
checkstyle {
maxWarnings = 0
toolVersion = "10.0"
}
//公用的依赖
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
// springboot
api("org.springframework.boot:spring-boot-starter-web")
api("org.springframework.boot:spring-boot-starter-aop")
api("org.springframework.boot:spring-boot-starter-validation")
api("org.springframework.boot:spring-boot-starter-data-redis")
api("org.springframework.boot:spring-boot-starter-actuator")
}
test {
useJUnitPlatform()
}
}
project(":xxx") {
subprojects {
dependencies {
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
testAnnotationProcessor("org.projectlombok:lombok")
}
}
}
最终实现方式
BOM+.gradle
实际使用过程中,发现只有BOM的话,在项目组成员不太熟悉的情况下使用,不太方便直观。
如果只用version.gradle确实简单直观,但是如果是多个项目的话,容易造成各自为战,每个项目都单独维护着自己的依赖版本。
综合项目组的实际情况考虑下来,决定将两个方式综合一下。
对于SpringBoot的组件使用Gradle插件来维护
对于所有项目中都会使用的依赖使用自定义 BOM 来维护
在项目的根目录下建议version.gradle来维护本项目中会使用到的依赖版本
注:version.gradle中定义的版本会覆盖BOM中定义的
version.gradle文件同上,这部分主要是对build.gradle文件做修改,修改如下
import org.springframework.boot.gradle.plugin.SpringBootPlugin
buildscript {
String cmd = 'git config core.hooksPath githooks'
cmd.execute().text.trim()
ext {
xx_bom = "com.xx.xx:xx-bom:0.0.12"
}
//设置仓库
repositories {
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://repo.spring.io/milestone' }
}
}
plugins {
id 'checkstyle'
id 'org.springframework.boot' version '2.7.5'
id 'io.spring.dependency-management' version '1.0.10.RELEASE'
}
//配置全局, 包括root项目和子项目
allprojects {
group 'com.xx'
version '1.0-SNAPSHOT'
apply plugin: 'io.spring.dependency-management'
//配置编码格式
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
//设置仓库
repositories {
maven { url "https://maven.aliyun.com/nexus/content/groups/public/" }
mavenLocal()
mavenCentral()
maven {
allowInsecureProtocol = true
url "xx"
}
}
}
apply from: 'version.gradle'
//配置所有子项目
subprojects {
apply plugin: 'java'
apply plugin: 'java-library' //api
apply plugin: 'checkstyle'
group 'com.miluo'
version '1.0-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
// dependencyManagement版本统一管理,类似于父maven的dependencyManagement
dependencyManagement {
dependencies {
for (depJar in rootProject.ext.dependencies) {
dependency depJar.value
}
}
}
checkstyle {
maxWarnings = 0
toolVersion = "10.0"
}
//公用的依赖
dependencies {
api(enforcedPlatform(SpringBootPlugin.BOM_COORDINATES))
api(platform("${xx_bom}"))
annotationProcessor(platform("${xx_bom}"))
testAnnotationProcessor(platform("${xx_bom}"))
testImplementation(platform("${xx_bom}"))
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
// springboot
api("org.springframework.boot:spring-boot-starter-web")
api("org.springframework.boot:spring-boot-starter-aop")
api("org.springframework.boot:spring-boot-starter-validation")
api("org.springframework.boot:spring-boot-starter-data-redis")
api("org.springframework.boot:spring-boot-starter-actuator")
}
test {
useJUnitPlatform()
}
}
project(":xx") {
apply plugin: 'io.spring.dependency-management'
subprojects {
dependencies {
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")
testAnnotationProcessor("org.projectlombok:lombok")
}
}
}
后续改进
BOM中定义的公共依赖过于笼统,应该按照功能分为多个来维护。