Java Gradle 实战指南:从 Wrapper、Kotlin DSL 到 Spring Boot 多模块构建

简介

Gradle 是 Java 生态里常见的构建工具。

它负责把一个项目从源码变成可运行、可测试、可发布的构建产物。

一个 Java 项目通常会涉及这些事情:

text 复制代码
下载依赖
编译源码
处理资源文件
运行测试
打包 jar / bootJar
发布到 Maven 仓库
组织多模块构建

Gradle 的核心特点是:

text 复制代码
用插件提供构建能力
用任务组织构建动作
用 DSL 描述构建配置
用 Wrapper 固定项目 Gradle 版本

一句话概括:

text 复制代码
Gradle 是一个灵活、可扩展、支持增量构建和多模块工程的现代构建工具。

Gradle 解决什么问题

没有构建工具时,Java 项目需要手动处理很多事情:

text 复制代码
手动下载 jar
手动配置 classpath
手动执行 javac
手动运行测试
手动打包 jar
手动处理多模块编译顺序

项目小的时候还能接受,项目变大后很容易失控。

Gradle 的做法是:

text 复制代码
标准目录约定
声明依赖
应用插件
执行任务
自动计算任务顺序
复用构建缓存

比如执行:

bash 复制代码
./gradlew build

Gradle 会自动完成:

text 复制代码
读取 settings.gradle.kts
读取 build.gradle.kts
解析插件和依赖
编译 main 代码
编译 test 代码
运行测试
打包产物
生成构建结果

Gradle 和 Maven 的关系

Gradle 和 Maven 都是构建工具,都能使用 Maven 仓库里的依赖。

区别主要在写法和构建模型上。

对比项 Maven Gradle
配置文件 pom.xml build.gradle / build.gradle.kts
配置风格 XML Groovy DSL / Kotlin DSL
生命周期 固定生命周期 任务图 DAG
插件机制 插件绑定生命周期阶段 插件添加任务和扩展
灵活性 约定强,写法稳定 可编程能力更强
多模块 父 POM + modules settings include + project dependency
依赖仓库 Maven 仓库 Maven 仓库、Ivy 仓库等

Maven 更像:

text 复制代码
按照固定生命周期跑标准流程。

Gradle 更像:

text 复制代码
根据任务依赖关系生成任务图,再按任务图执行。

Gradle Wrapper

实际项目里通常不直接使用本机的 gradle 命令,而是使用 Gradle Wrapper。

bash 复制代码
./gradlew build

Windows 下是:

bash 复制代码
gradlew.bat build

Wrapper 的作用是让项目固定使用某个 Gradle 版本。

常见文件结构:

text 复制代码
gradle-demo/
├── gradlew
├── gradlew.bat
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── settings.gradle.kts
└── build.gradle.kts

gradle-wrapper.properties 里会指定 Gradle 发行包地址:

properties 复制代码
distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip

这样无论本机是否安装 Gradle,只要有 JDK,就可以通过 ./gradlew 执行构建。

生成 Wrapper:

bash 复制代码
gradle wrapper --gradle-version 9.6.1

升级 Wrapper:

bash 复制代码
./gradlew wrapper --gradle-version 9.6.1

项目里的 Wrapper 文件应该提交到 Git。

这样 CI、开发机、构建服务器都能使用同一个 Gradle 版本。

Gradle 运行 JDK 和项目编译 JDK

Gradle 自己运行需要 JVM。

当前 Gradle 9.x 要求运行 Gradle 的 JVM 至少是 Java 17。

但项目代码编译使用哪个 JDK,可以通过 Java Toolchain 单独指定。

kotlin 复制代码
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

这表示:

text 复制代码
Gradle 自己可以运行在 Java 17+
项目源码使用 Java 21 工具链编译

Toolchain 的好处是构建更稳定。

不同机器上的 JAVA_HOME 不一致时,Gradle 仍然可以选择符合要求的 JDK 来编译项目。

Gradle 项目目录

标准 Java 项目目录和 Maven 很接近。

text 复制代码
gradle-java-demo/
├── settings.gradle.kts
├── build.gradle.kts
├── gradle.properties
├── gradlew
├── gradlew.bat
├── gradle/
│   └── wrapper/
└── src/
    ├── main/
    │   ├── java/
    │   └── resources/
    └── test/
        ├── java/
        └── resources/

几个核心文件:

文件 作用
settings.gradle.kts 设置根项目名称、声明子模块、配置插件仓库
build.gradle.kts 当前项目或模块的构建脚本
gradle.properties Gradle 参数、项目属性
gradlew macOS / Linux Wrapper 命令
gradlew.bat Windows Wrapper 命令
gradle-wrapper.properties Wrapper 使用的 Gradle 版本

settings.gradle.kts

单模块项目:

kotlin 复制代码
pluginManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
}

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        mavenCentral()
    }
}

rootProject.name = "gradle-java-demo"

多模块项目:

kotlin 复制代码
rootProject.name = "mall-system"

include("mall-common")
include("mall-domain")
include("mall-service")
include("mall-web")

settings.gradle.kts 是 Gradle 初始化阶段会读取的文件。

它决定这次构建包含哪些项目。

build.gradle.kts 基础模板

下面是一个普通 Java 应用的 build.gradle.kts。

kotlin 复制代码
plugins {
    java
    application
}

group = "com.example"
version = "1.0.0-SNAPSHOT"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.slf4j:slf4j-api:2.0.18")
    runtimeOnly("ch.qos.logback:logback-classic:1.5.15")

    testImplementation("org.junit.jupiter:junit-jupiter:5.11.4")
}

application {
    mainClass.set("com.example.demo.MainApplication")
}

tasks.test {
    useJUnitPlatform()
}

这个文件做了几件事:

配置 作用
plugins 应用 Java 和 Application 插件
group 项目组织名
version 项目版本
java.toolchain 指定 Java 编译工具链
repositories 依赖从哪里下载
dependencies 项目依赖
application.mainClass 可运行应用入口类
tasks.test 配置测试任务

Groovy DSL 和 Kotlin DSL

Gradle 支持两种常见 DSL:

文件 DSL
build.gradle Groovy DSL
build.gradle.kts Kotlin DSL

Groovy DSL:

groovy 复制代码
plugins {
    id 'java'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

Kotlin DSL:

kotlin 复制代码
plugins {
    java
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
}

Kotlin DSL 的类型提示和 IDE 补全通常更好,新项目可以优先使用 build.gradle.kts。

老项目里遇到 build.gradle 也很正常。

常用命令

日常命令通常使用 Wrapper。

bash 复制代码
./gradlew tasks

查看所有任务。

bash 复制代码
./gradlew clean

清理 build 目录。

bash 复制代码
./gradlew compileJava

编译 main 源码。

bash 复制代码
./gradlew test

运行测试。

bash 复制代码
./gradlew build

完整构建,通常包含编译、测试、打包。

bash 复制代码
./gradlew jar

打普通 jar。

bash 复制代码
./gradlew dependencies

查看依赖树。

bash 复制代码
./gradlew dependencyInsight --dependency logback-classic

查看某个依赖为什么被引入。

bash 复制代码
./gradlew build -x test

构建时跳过测试。

构建生命周期

Gradle 构建有三个阶段:

阶段 做什么
初始化 读取 settings.gradle.kts,确定参与构建的项目
配置 读取各模块 build.gradle.kts,配置 Project 和 Task
执行 根据任务图执行被请求的任务

执行:

bash 复制代码
./gradlew build

Gradle 不会简单地从上到下跑脚本。

它会先生成任务图,再执行任务图里的任务。

比如 build 可能依赖:

text 复制代码
compileJava
processResources
classes
compileTestJava
test
jar
assemble
check

插件会向项目添加任务,任务之间可以声明依赖关系。

Task 是 Gradle 的执行单元

查看任务:

bash 复制代码
./gradlew tasks

自定义一个简单任务:

kotlin 复制代码
tasks.register("hello") {
    group = "demo"
    description = "打印一条 Gradle 消息"

    doLast {
        println("Hello Gradle")
    }
}

执行:

bash 复制代码
./gradlew hello

任务依赖:

kotlin 复制代码
tasks.register("packageInfo") {
    dependsOn("test")

    doLast {
        println("测试通过后生成打包信息")
    }
}

dependsOn("test") 表示执行 packageInfo 前先执行 test。

Plugin 是能力入口

Gradle 很多能力都来自插件。

比如 Java 插件:

kotlin 复制代码
plugins {
    java
}

它会添加:

text 复制代码
compileJava
processResources
classes
jar
compileTestJava
test
build

Application 插件:

kotlin 复制代码
plugins {
    application
}

它会添加:

text 复制代码
run
installDist
distZip
distTar

Spring Boot 插件:

kotlin 复制代码
plugins {
    id("org.springframework.boot") version "3.5.0"
    id("io.spring.dependency-management") version "1.1.7"
    java
}

它会添加:

text 复制代码
bootRun
bootJar
bootBuildImage

简单理解:

text 复制代码
插件负责把某类构建能力接入项目。
任务负责真正执行构建动作。

依赖配置怎么选

Gradle 依赖不是只有一个 compile。

常见配置如下:

配置 说明
implementation 编译和运行需要,但不暴露给依赖当前模块的其他模块
api 编译和运行需要,并暴露给依赖当前模块的其他模块
compileOnly 编译需要,运行时由环境提供
runtimeOnly 编译不需要,运行时需要
testImplementation 测试编译和运行需要
testRuntimeOnly 测试运行时需要
annotationProcessor 注解处理器,比如 Lombok、MapStruct

示例:

kotlin 复制代码
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")

    compileOnly("org.projectlombok:lombok")
    annotationProcessor("org.projectlombok:lombok")

    runtimeOnly("com.mysql:mysql-connector-j")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

implementation 和 api 的区别在多模块里很重要。

假设:

text 复制代码
mall-web -> mall-service -> mall-domain

如果 mall-service 的公开方法签名里暴露了 mall-domain 类型,就可以用 api(project(":mall-domain"))。

如果只是内部使用,就用 implementation(project(":mall-domain"))。

使用 api 需要应用 java-library 插件:

kotlin 复制代码
plugins {
    `java-library`
}

依赖排除和版本冲突

排除传递依赖:

kotlin 复制代码
dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web") {
        exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat")
    }
}

查看依赖来源:

bash 复制代码
./gradlew dependencyInsight --dependency spring-boot-starter-tomcat

刷新依赖缓存:

bash 复制代码
./gradlew --refresh-dependencies build

Gradle 会做版本冲突解析,通常选择较高版本。

Spring Boot 项目一般交给 Boot 的 BOM 和依赖管理控制版本,业务模块少手写三方依赖版本。

Version Catalog:集中管理依赖版本

多模块项目里,依赖版本散落在各个 build.gradle.kts 中会很难维护。

Gradle 推荐使用 Version Catalog。

文件位置:

text 复制代码
gradle/libs.versions.toml

示例:

toml 复制代码
[versions]
spring-boot = "3.5.0"
junit-jupiter = "5.11.4"
mapstruct = "1.6.3"

[libraries]
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
mapstruct = { module = "org.mapstruct:mapstruct", version.ref = "mapstruct" }
mapstruct-processor = { module = "org.mapstruct:mapstruct-processor", version.ref = "mapstruct" }

[plugins]
spring-boot = { id = "org.springframework.boot", version.ref = "spring-boot" }

build.gradle.kts 中使用:

kotlin 复制代码
plugins {
    alias(libs.plugins.spring.boot)
    java
}

dependencies {
    implementation(libs.mapstruct)
    annotationProcessor(libs.mapstruct.processor)
    testImplementation(libs.junit.jupiter)
}

这样版本集中在一个文件里,多模块升级更方便。

Spring Boot Gradle 项目

一个常见 Spring Boot 单模块配置如下:

kotlin 复制代码
plugins {
    java
    id("org.springframework.boot") version "3.5.0"
    id("io.spring.dependency-management") version "1.1.7"
}

group = "com.example"
version = "1.0.0"

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-validation")
    runtimeOnly("com.mysql:mysql-connector-j")

    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.test {
    useJUnitPlatform()
}

开发阶段运行:

bash 复制代码
./gradlew bootRun

打生产包:

bash 复制代码
./gradlew clean bootJar

产物一般在:

text 复制代码
build/libs/

运行:

bash 复制代码
java -jar build/libs/demo-1.0.0.jar

bootJar 会生成 Spring Boot 可执行 jar。

普通 jar 任务生成的是普通 jar,通常不包含 Spring Boot 启动所需的嵌套依赖结构。

bootRun、bootJar、jar 的区别

任务 作用 常见命令
bootRun 直接从源码和 runtime classpath 启动 Spring Boot 应用 ./gradlew bootRun
bootJar 打 Spring Boot 可执行 jar ./gradlew bootJar
jar 打普通 jar ./gradlew jar
build 执行完整构建,通常会包含测试和打包 ./gradlew build

开发阶段常用:

bash 复制代码
./gradlew bootRun

CI 或发版阶段常用:

bash 复制代码
./gradlew clean build

或者只打 Spring Boot 可执行包:

bash 复制代码
./gradlew clean bootJar

多模块项目

一个典型多模块结构:

text 复制代码
mall-system/
├── settings.gradle.kts
├── build.gradle.kts
├── mall-common/
│   └── build.gradle.kts
├── mall-domain/
│   └── build.gradle.kts
├── mall-service/
│   └── build.gradle.kts
└── mall-web/
    └── build.gradle.kts

settings.gradle.kts:

kotlin 复制代码
rootProject.name = "mall-system"

include("mall-common")
include("mall-domain")
include("mall-service")
include("mall-web")

根 build.gradle.kts:

kotlin 复制代码
plugins {
    java
    id("org.springframework.boot") version "3.5.0" apply false
    id("io.spring.dependency-management") version "1.1.7" apply false
}

allprojects {
    group = "com.example"
    version = "1.0.0"

    repositories {
        mavenCentral()
    }
}

subprojects {
    apply(plugin = "java")

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(21)
        }
    }

    tasks.withType<Test>().configureEach {
        useJUnitPlatform()
    }
}

mall-service/build.gradle.kts:

kotlin 复制代码
plugins {
    `java-library`
}

dependencies {
    api(project(":mall-domain"))
    implementation(project(":mall-common"))
}

mall-web/build.gradle.kts:

kotlin 复制代码
plugins {
    id("org.springframework.boot")
    id("io.spring.dependency-management")
}

dependencies {
    implementation(project(":mall-service"))
    implementation("org.springframework.boot:spring-boot-starter-web")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

构建整个项目:

bash 复制代码
./gradlew clean build

只构建某个模块:

bash 复制代码
./gradlew :mall-web:build

只运行 Web 模块:

bash 复制代码
./gradlew :mall-web:bootRun

gradle.properties

gradle.properties 常用于放 Gradle 构建参数和项目属性。

properties 复制代码
org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
org.gradle.parallel=true
org.gradle.caching=true

projectVersion=1.0.0

在 build.gradle.kts 中读取:

kotlin 复制代码
version = providers.gradleProperty("projectVersion").get()

常见配置:

配置 作用
org.gradle.jvmargs Gradle Daemon JVM 参数
org.gradle.parallel 多项目并行构建
org.gradle.caching 启用构建缓存
自定义属性 项目版本、仓库地址等

账号、Token、私服密码不适合直接提交到项目仓库。

这类信息可以放到用户目录的 ~/.gradle/gradle.properties,或者由 CI 环境变量注入。

发布到 Maven 仓库

Gradle 可以用 maven-publish 插件发布构建产物。

kotlin 复制代码
plugins {
    `java-library`
    `maven-publish`
}

group = "com.example"
version = "1.0.0"

publishing {
    publications {
        create<MavenPublication>("mavenJava") {
            from(components["java"])
        }
    }

    repositories {
        maven {
            name = "localRepo"
            url = uri(layout.buildDirectory.dir("repo"))
        }
    }
}

发布到本地 Maven 仓库:

bash 复制代码
./gradlew publishToMavenLocal

发布到配置的仓库:

bash 复制代码
./gradlew publish

公共库、内部 SDK、多模块基础组件,经常会用到发布能力。

自定义任务示例:生成构建信息

下面定义一个任务,生成 build/generated/build-info.txt。

kotlin 复制代码
abstract class GenerateBuildInfoTask : DefaultTask() {

    @get:OutputFile
    abstract val outputFile: RegularFileProperty

    @TaskAction
    fun generate() {
        outputFile.get().asFile.writeText(
            """
            name=${project.name}
            version=${project.version}
            time=${java.time.Instant.now()}
            """.trimIndent()
        )
    }
}

tasks.register<GenerateBuildInfoTask>("generateBuildInfo") {
    outputFile.set(layout.buildDirectory.file("generated/build-info.txt"))
}

执行:

bash 复制代码
./gradlew generateBuildInfo

Gradle 任务可以声明输入和输出。

输入输出声明清楚后,Gradle 才能更好地做增量构建和缓存。

IDEA 里 Gradle 面板怎么理解

IDEA 的 Gradle 面板通常会展示:

text 复制代码
Tasks
Dependencies
Plugins

Tasks 是可以执行的任务。

比如:

text 复制代码
build
clean
test
bootRun
bootJar
dependencies

双击任务,本质上类似执行:

bash 复制代码
./gradlew bootRun

Plugins 是当前项目应用的插件。

插件会贡献任务和配置项。

比如 Spring Boot 插件贡献 bootRun、bootJar,Java 插件贡献 compileJava、test、jar。

所以 IDEA 里真正执行的是任务,不是插件本身。

常见问题

gradle 和 gradlew 用哪个

项目内优先使用:

bash 复制代码
./gradlew build

它会使用项目指定的 Gradle 版本。

本机 gradle 更适合初始化 Wrapper 或做临时实验。

build 和 bootJar 有什么区别

bootJar 只负责生成 Spring Boot 可执行 jar。

build 是生命周期任务,会执行检查、测试、打包等一组任务。Spring Boot 项目里,build 通常也会触发 bootJar。

为什么依赖下载很慢

常见原因是网络、仓库源、公司代理。

可以在 settings.gradle.kts 或企业统一 Gradle 配置里设置仓库。

kotlin 复制代码
repositories {
    mavenCentral()
    maven("https://maven.aliyun.com/repository/public")
}

企业项目更推荐使用内部 Nexus、Artifactory 这类私服。

为什么修改代码后没有重新编译全部内容

Gradle 支持增量构建。

如果输入和输出没有变化,对应任务可能显示 UP-TO-DATE。

text 复制代码
> Task :compileJava UP-TO-DATE

这表示 Gradle 判断该任务不需要重新执行。

implementation 和 api 怎么选

默认优先用 implementation。

只有当前模块的公开 API 暴露了某个依赖类型时,才考虑 api。

这样可以减少无关依赖传递,提高编译隔离效果。

Spring Boot 项目能不能只执行 jar

可以执行 jar,但它生成的是普通 jar。

Spring Boot 应用通常使用:

bash 复制代码
./gradlew bootJar

bootJar 生成的 jar 才包含 Spring Boot 可执行应用所需的启动结构。

实践建议

场景 建议
项目构建 使用 ./gradlew
新项目 DSL 优先使用 Kotlin DSL
Java 版本 使用 java.toolchain 固定
Spring Boot 运行 开发阶段用 bootRun
Spring Boot 打包 发版阶段用 clean bootJar 或 clean build
多模块依赖 默认 implementation,必要时 api
依赖版本 多模块使用 Version Catalog
依赖排查 使用 dependencies 和 dependencyInsight
构建性能 开启缓存、并行构建,避免低质量自定义任务
敏感配置 放到用户级 Gradle 配置或 CI 环境变量

小结

Gradle 的核心不是某个单独命令,而是一套任务驱动的构建模型。

Wrapper 负责固定 Gradle 版本,settings.gradle.kts 决定构建包含哪些项目,build.gradle.kts 描述插件、依赖和任务,插件贡献具体构建能力,任务组成最终的执行图。

普通 Java 项目关注 java、application、test、jar。Spring Boot 项目还要关注 bootRun 和 bootJar。多模块项目则要进一步关注 settings.gradle.kts、模块依赖、api / implementation、Version Catalog 和统一构建配置。

把这些概念串起来后,Gradle 就不只是"能打包"的工具,而是可以支撑复杂工程构建、依赖治理和持续交付的构建系统。

相关推荐
我是人✓20 分钟前
Spring IOC注解全解析和Spring整合测试单元
java·后端·spring
智购科技无人售货机工厂店27 分钟前
玻璃瓶饮料破损率突然上升,排查发现是取货口缓冲垫老化了~YH
java·开发语言·人工智能·python·eclipse
镜象科技36 分钟前
中小学AI心理健康解决方案服务商怎么选?2026年选型参考
android·java·人工智能
阿狗童鞋42 分钟前
高并发系统设计实战指南
java·spring boot·spring cloud
Sam_Deep_Thinking1 小时前
CountDownLatch实现原理
java·后端·面试·程序员
小狼Solar1 小时前
SAP MDG 功能范围说明(基于S/4HANA 2025)
java·开发语言
范中勤1 小时前
Python 与 Java:模块、包、对象、反射核心差异总结
java·python·面试·反射·元类
ab1237681 小时前
Spring Integration 完整笔记 + 和 spring-integration-mqtt、Paho、EMQX 的关系
java·笔记·spring
小蜗牛狂飙记1 小时前
java环境一键配置和切换的ui工具
java
逆光的July1 小时前
可靠消息投递与消费的工程设计:Outbox、幂等、死信兜底
java