場景描述
在maven里可以在pom.xml中統(tǒng)一定義項目依賴,依賴版本,插件,多環(huán)境構建,子模塊;定義packaging 為pom類型,各子模塊按需引入,并且指定環(huán)境profiles構建。
在gradle中也可以實現依賴統(tǒng)一管理,各模塊按需引入,區(qū)分環(huán)境的構建任務。
先上效果圖
統(tǒng)一定義依賴,依賴版本,插件
子模塊按需引入
分環(huán)境打包task及docker鏡像打包任務
環(huán)境
gradle8.1.1, springboot3.1.0, jdk17
步驟
- 創(chuàng)建項目
通過IDEA或Spring Initializer 創(chuàng)建springboot+kotlin+gradle的基礎項目; - 修改gradle/wrapper/gradle-wrapper.properties 中gradle版本 https://services.gradle.org/distributions/gradle-8.1.1-bin.zip
- 統(tǒng)一定義依賴,版本,插件;由gradle catalogs實現,catalogs官方文檔介紹
- 在根目錄創(chuàng)建libs.versions.toml 文件,自己當前項目文件內容如下
#### 定義項目所有依賴庫
## 統(tǒng)一定義版本
[versions]
project-version= "0.0.1"
springboot = "3.1.0"
kotlin = "1.8.21"
docker-plugin = "9.3.0"
mybatis-plus = "3.5.3"
velocity = "2.0"
mysql = "8.0.32"
hutool = "5.8.17"
knife4j = "4.3.0"
easyexcel = "3.2.1"
dynamic-datasource = "3.6.0"
sa-token = "1.35.0.RC"
spring-cloud = "2022.0.2"
spring-cloud-alibaba = "2022.0.0.0-RC2"
spring-doc = "2.1.0"
spring-redisson = "3.21.3"
dubbo = "3.2.0"
aliyun-sms = "2.0.23"
fastjson2 = "2.0.39"
dingtalk-service-sdk = "2.0.0"
dingtalk-sdk = "2.0.29"
flowable = "7.0.0.M1"
liteflow = "2.10.5"
rocketmq = "2.2.3"
minio = "8.5.4"
## 統(tǒng)一定義依賴
[libraries]
mybatis-plus = { module = "com.baomidou:mybatis-plus-boot-starter", version.ref = "mybatis-plus" }
mybatis-generator = { module = "com.baomidou:mybatis-plus-generator", version.ref = "mybatis-plus" }
velocity = { module = "org.apache.velocity:velocity-engine-core", version.ref = "velocity" }
mysql = { module = "mysql:mysql-connector-java", version.ref = "mysql" }
# 使用的是springdoc-openapi3, https://springdoc.org/#migrating-from-springfox 不再是springfox
knife4j = { module = "com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter", version.ref = "knife4j" }
knife4j-gateway = { module = "com.github.xiaoymin:knife4j-gateway-spring-boot-starter", version.ref = "knife4j" }
hutool-core = { module = "cn.hutool:hutool-core", version.ref = "hutool" }
hutool-captcha = { module = "cn.hutool:hutool-captcha", version.ref = "hutool" }
hutool-crypto = { module = "cn.hutool:hutool-crypto", version.ref = "hutool" }
hutool-http = { module = "cn.hutool:hutool-http", version.ref = "hutool" }
hutool-extra = { module = "cn.hutool:hutool-extra", version.ref = "hutool" }
hutool-json = { module = "cn.hutool:hutool-json", version.ref = "hutool" }
easyexcel = { module = "com.alibaba:easyexcel", version.ref = "easyexcel" }
satoken-core = { module = "cn.dev33:sa-token-core", version.ref = "sa-token" }
satoken-web = { module = "cn.dev33:sa-token-spring-boot3-starter", version.ref = "sa-token" }
satoken-reactor = { module = "cn.dev33:sa-token-reactor-spring-boot3-starter", version.ref = "sa-token" }
satoken-dubbo = { module = "cn.dev33:sa-token-dubbo", version.ref = "sa-token" }
dynamic-datasource = { module = "com.baomidou:dynamic-datasource-spring-boot-starter", version.ref = "dynamic-datasource" }
spring-boot = { module = "org.springframework.boot:spring-boot-dependencies", version.ref = "springboot" }
spring-cloud = { module = "org.springframework.cloud:spring-cloud-dependencies", version.ref = "spring-cloud" }
spring-cloud-alibaba = { module = "com.alibaba.cloud:spring-cloud-alibaba-dependencies", version.ref = "spring-cloud-alibaba" }
spring-doc-common = { module = "org.springdoc:springdoc-openapi-starter-common", version.ref = "spring-doc" }
spring-doc-webflux = { module = "org.springdoc:springdoc-openapi-starter-webflux-ui", version.ref = "spring-doc" }
spring-doc-webmvc = { module = "org.springdoc:springdoc-openapi-starter-webmvc-ui", version.ref = "spring-doc" }
spring-redisson = { module = "org.redisson:redisson-spring-boot-starter", version.ref = "spring-redisson" }
spring-dubbo = { module = "org.apache.dubbo:dubbo-spring-boot-starter", version.ref = "dubbo" }
dubbo = { module = "org.apache.dubbo:dubbo", version.ref = "dubbo" }
dubbo-nacos = { module = "org.apache.dubbo:dubbo-registry-nacos", version.ref = "dubbo" }
aliyun-sms = { module = "com.aliyun:dysmsapi20170525", version.ref = "aliyun-sms" }
kotlin-fastjosn2 = { module = "com.alibaba.fastjson2:fastjson2-kotlin", version.ref = "fastjson2" }
dingtalk-service = { module = "com.aliyun:alibaba-dingtalk-service-sdk", version.ref = "dingtalk-service-sdk" }
dingtalk-sdk = { module = "com.aliyun:dingtalk", version.ref = "dingtalk-sdk" }
flowable = { module = "org.flowable:flowable-spring-boot-starter", version.ref = "flowable" }
flowable-bpmn-layout = { module = "org.flowable:flowable-bpmn-layout", version.ref = "flowable" }
liteflow = { module = "com.yomahub:liteflow-spring-boot-starter", version.ref = "liteflow" }
rocketmq = { module = "org.apache.rocketmq:rocketmq-spring-boot-starter", version.ref = "rocketmq" }
minio = { module = "io.minio:minio", version.ref = "minio" }
## 將多個需要同時引入的依賴定義成一個組,使用時直接引入組
[bundles]
hutool = ["hutool-core", "hutool-captcha", "hutool-crypto", "hutool-http", "hutool-extra", "hutool-json"]
spring-doc = ["spring-doc-common", "spring-doc-webflux", "spring-doc-webmvc"]
datasource = ["mysql", "dynamic-datasource"]
dubbo = ["dubbo", "spring-dubbo", "dubbo-nacos", "kotlin-fastjosn2", "satoken-dubbo"]
mybatisplus-generator = ["mybatis-generator", "velocity"]
flowable = ["flowable", "flowable-bpmn-layout"]
## 統(tǒng)一定義插件
[plugins]
springboot = { id = "org.springframework.boot", version.ref = "springboot" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" }
docker = { id = "com.bmuschko.docker-spring-boot-application", version.ref = "docker-plugin" }
- 在根目錄settings.gradle.kts 引入依賴文件,順便定義全局鏡像倉庫
import java.net.URI
dependencyResolutionManagement {
repositories {
// 使用阿里云 鏡像倉庫
maven {url = URI("https://maven.aliyun.com/nexus/content/groups/public/") }
//私庫
maven { url = URI("xxx") }
mavenCentral()
}
// 統(tǒng)一依賴庫定義
versionCatalogs {
create("projectLibs"){
from(files("./libs.versions.toml"))
}
}
}
rootProject.name = "project-name"
- 在根目錄build.gradle.kts配置項目和子模塊通用構建配置,直接貼文件內容,有注釋說明
import org.apache.tools.ant.filters.ReplaceTokens
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.io.FileInputStream
import java.util.*
// 引入插件
plugins {
alias(projectLibs.plugins.springboot)
alias(projectLibs.plugins.kotlin.jvm)
alias(projectLibs.plugins.kotlin.spring)
alias(projectLibs.plugins.docker)
}
// 定義庫引用
val pLibs = projectLibs
// 加載根路徑自定義配置屬性 用于替換打包時不同環(huán)境的變量值
val envProps = Properties()
envProps.load(FileInputStream("${project.projectDir.absolutePath}${File.separator}env.properties"))
subprojects {
// 全部項目有基礎插件kotlin jvm/spring
apply {
plugin(pLibs.plugins.kotlin.jvm.get().pluginId)
plugin(pLibs.plugins.kotlin.spring.get().pluginId)
}
// 統(tǒng)一group和version
group = "xxx"
version = pLibs.versions.project.version.get()
java.sourceCompatibility = JavaVersion.VERSION_17
dependencies {
// bom 管理著一組依賴的版本,各模塊按需引入其中的依賴即可,由bom統(tǒng)一約束著版本,
// spring boot bom
implementation(platform(pLibs.spring.boot))
// spring cloud bom
implementation(platform(pLibs.spring.cloud))
// spring cloud alibaba bom
implementation(platform(pLibs.spring.cloud.alibaba))
}
// 排序logback, 使用log4j2
configurations.all {
exclude("org.springframework.boot","spring-boot-starter-logging")
exclude("ch.qos.logback")
}
tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict", "-Xjvm-default=all")
jvmTarget = "17"
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.jar {
enabled = true
archiveClassifier.set("")
}
// 為擁有bootJar的模塊創(chuàng)建dev,test,prod的構建任務
if (getTasksByName("bootJar", false).isNotEmpty()) {
println("getTask:::" + getTasksByName("bootJar", false))
tasks.register<Jar>("bootJar-dev") { buildJarTaskConf(this, "dev") }
tasks.register<Jar>("bootJar-test") { buildJarTaskConf(this, "test") }
tasks.register<Jar>("bootJar-prod") { buildJarTaskConf(this, "prod") }
// docker鏡像
apply {
plugin(pLibs.plugins.docker.get().pluginId)
}
docker {
// docker鏡像倉庫配置
registryCredentials {
url.set("http://ip:port")
username.set("username")
password.set("password")
}
springBootApplication {
baseImage.set("xxxx/java:17-latest")
images.set(setOf("xxx/$name:$version"))
jvmArgs.set(listOf("-Dfile.encoding=utf-8"))
}
}
// docker測試環(huán)境構建并推送鏡像任務
tasks.register<Jar>("dockerBuildAndPushImage-test") { buildDockerTaskConf(this, "test") }
}
// 包含有bootjar的模塊在processResources 任務階段替換環(huán)境變量
if (getTasksByName("bootJar", false).isNotEmpty() || project.name == "xxx-module") {
// 在復制文件任務processResources階段替換變量
tasks.processResources {
doFirst { // 將邏輯放到執(zhí)行階段
val env = System.getProperty("buildEnv", "dev") // 默認dev環(huán)境
println("===============模塊 ${project.name} 替換配置文件環(huán)境變量 , 構建環(huán)境: $env ==================")
filter(
ReplaceTokens::class,
"tokens" to
// envPropsToMap(env)
// todo 寫個函數自動讀取待替換列表轉為map
mapOf(
"nacos.server" to envProps.getOrElse("env.$env.nacos.server") {
throw IllegalArgumentException(
"未找到環(huán)境:$env 屬性:nacos.server 的配置"
)
},
"nacos.namespace" to envProps.getOrElse("env.$env.nacos.namespace") {
throw IllegalArgumentException(
"未找到環(huán)境:$env 屬性:nacos.namespace 的配置"
)
},
"nacos.username" to envProps.getOrDefault("env.$env.nacos.username", ""),
"nacos.password" to envProps.getOrDefault("env.$env.nacos.password", ""),
"active.env" to env
)
)
filteringCharset = "UTF-8"
}
}
tasks.classes {
dependsOn("clean")
}
}
}
// docker服務地址
docker {
url.set("tcp://xxx:2375")
}
/**
* 任務執(zhí)行順序說明
* Task#finalizedBy 函數 的作用是為 Gradle 任務 設置任務執(zhí)行完畢后執(zhí)行的任務,A.finalizedBy B 的作用是 A 任務執(zhí)行完畢后 , 執(zhí)行 B 任務
* A.finalizedBy B
* B.dependsOn C
* A 執(zhí)行完畢后執(zhí)行 B , B 依賴于 C , 執(zhí)行 B 之前要先把 C 執(zhí)行了。A -> C -> B
*/
/**
* 構建各個環(huán)境的bootJar
*/
fun buildJarTaskConf(jarTask: Jar, env: String) {
jarTask.group = "build"
jarTask.dependsOn("clean")
jarTask.doFirst {
println("=============== 構建 ${jarTask.archiveFileName.get()} 包 , 構建環(huán)境: $env ==================")
System.setProperty("buildEnv", env)
}
jarTask.finalizedBy("bootJar")
}
fun buildDockerTaskConf(dockerPushImage: Jar, env: String) {
dockerPushImage.group = "docker"
dockerPushImage.doFirst {
System.setProperty("buildEnv", env)
}
dockerPushImage.finalizedBy("dockerPushImage")
}
- 根目錄創(chuàng)建env.properties
## dev
env.dev.nacos.server=xxx:8848
env.dev.nacos.namespace=xxx
env.dev.nacos.username=xx
env.dev.nacos.password=xx
## test
env.test.nacos.server=xxx:8848
env.test.nacos.namespace=xxx
env.test.nacos.username=xx
env.test.nacos.password=xx
## prod
env.prod.nacos.server=xxx:8848
env.prod.nacos.namespace=xxx
env.prod.nacos.username=xxx
env.prod.nacos.password=xxx
- 創(chuàng)建Module, 一種是包含springboot啟動類的模塊, 一種是作為公共定義的模塊
9. 包含springboot啟動類的模塊的build.gradle.kts文件
公共定義的模塊的build.gradle.kts文件
- 在公共定義模塊多了的情況,有些模塊可能會出現互相依賴,這時候需要解決,解決方式
- 盡可能依賴最小模塊,比如只引入mybatisplus-core
- 抽取出來作為公共模塊
- springboot3 自動配置類,將引入模塊的配置注入spring
- 盡可能依賴最小模塊,比如只引入mybatisplus-core
撒花~文章來源:http://www.zghlxwxcb.cn/news/detail-763443.html
補充一個demo工程,不是文中的工程,文中的為微服務,該demo為單一服務 gitee地址文章來源地址http://www.zghlxwxcb.cn/news/detail-763443.html
到了這里,關于springboot gradle kotlin 多模塊(或微服務)統(tǒng)一依賴及版本管理和構建不同環(huán)境打包task,docker鏡像構建task的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!