首先使用 gradle init 创建一个 Java 应用,以此来学习编写 Gradle 构建脚本的基础知识。

在本节中,你将学习

  • 初始化 Java 项目

  • 查看目录结构

  • 运行 Java 应用

  • 生成构建扫描

  • 将应用打包成归档文件

步骤 0:开始之前

  1. 确保你已经安装了 Gradle

  2. 安装 IntelliJ IDEA。社区版是 IntelliJ IDEA 的免费版本。

步骤 1:初始化项目

创建一个名为 authoring-tutorial 的新目录并 cd 进入该目录

$ mkdir authoring-tutorial
$ cd authoring-tutorial

运行带参数的 gradle init 命令来生成一个 Java 应用

$ gradle init --type java-application  --dsl kotlin
$ gradle init --type java-application  --dsl groovy

对于所有额外的提示,选择默认选项。

在本教程中,所有示例均基于 macOS。

步骤 2:理解目录结构

项目根目录包含项目的所有源文件。

完成 Gradle init 后,目录结构应如下所示:

.
├── gradle                              (1)
    ├── libs.versions.toml              (2)
│   └── wrapper
├── gradlew                             (3)
├── gradlew.bat                         (3)
├── settings.gradle.kts                 (4)
└── app
    ├── build.gradle.kts                (5)
    └── src
        ├── main
        │   └── java                    (6)
        │       └── demo
        │           └── App.java
        └── test
            └── java                    (7)
                └── demo
                    └── AppTest.java
1 生成的 wrapper 文件目录
2 依赖项的版本目录
3 Gradle wrapper 启动脚本
4 用于定义构建名称和子项目的设置文件
5 app 子项目的构建脚本
6 app 子项目的默认 Java 源代码目录
7 app 子项目的默认 Java 测试源代码目录
.
├── gradle                              (1)
    ├── libs.versions.toml              (2)
│   └── wrapper
├── gradlew                             (3)
├── gradlew.bat                         (3)
├── settings.gradle                     (4)
└── app
    ├── build.gradle                    (5)
    └── src
        ├── main
        │   └── java                    (6)
        │       └── demo
        │           └── App.java
        └── test
            └── java                    (7)
                └── demo
                    └── AppTest.java
1 生成的 wrapper 文件目录
2 依赖项的版本目录
3 Gradle wrapper 启动脚本
4 用于定义构建名称和子项目的设置文件
5 app 子项目的构建脚本
6 app 子项目的默认 Java 源代码目录
7 app 子项目的默认 Java 测试源代码目录

authoring-tutorial 文件夹是根项目目录。在根项目目录中包含一个或多个子项目、构建脚本和 Gradle wrapper。

Gradle Wrapper 位于根项目本地,而 Gradle 可执行文件位于 GRADLE_USER_HOME 中。

GRADLE_USER_HOME 默认指向 USER_HOME/.gradle,Gradle 也在此存储其全局配置属性、初始化脚本、缓存、日志文件等内容。

步骤 3:查看 Gradle 文件

settings.gradle(.kts) 文件中有两行值得关注的代码:

settings.gradle.kts
rootProject.name = "authoring-tutorial"
include("app")
settings.gradle
rootProject.name = 'authoring-tutorial'
include('app')
  • rootProject.name 为构建分配一个名称,这会覆盖默认的以目录名作为构建名称的行为。

  • include("app") 定义了该构建包含一个名为 app 的子项目,该子项目包含其自身的源代码和构建逻辑。

可以通过添加额外的 include() 语句来添加更多子项目。

我们的构建包含一个名为 app 的子项目,它代表我们正在构建的 Java 应用。该子项目在 app/build.gradle(.kts) 文件中进行配置:

build.gradle.kts
plugins {
    id("application")                                               (1)
}

repositories {
    mavenCentral()                                                  (2)
}

dependencies {
    testImplementation(libs.junit.jupiter)                          (3)
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation(libs.guava)                                      (4)
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)                (5)
    }
}

application {
    mainClass = "org.example.App"                                   (6)
}

tasks.named<Test>("test") {
    useJUnitPlatform()                                              (7)
}
1 应用 application 插件以添加构建 Java CLI 应用的支持。
2 使用 Maven Central 来解析依赖项。
3 使用 JUnit Jupiter 进行测试(使用版本目录)。
4 应用使用了此依赖项(通过版本目录引用)。
5 定义工具链版本。
6 定义应用的主类。
7 使用 JUnit Platform 进行单元测试。
plugins {
    id 'application'                                                (1)
}

repositories {
    mavenCentral()                                                  (2)
}

dependencies {
    testImplementation libs.junit.jupiter                           (3)
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    implementation libs.guava                                       (4)
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(11)                (5)
    }
}

application {
    mainClass = 'org.example.App'                                   (6)
}

tasks.named('test') {
    useJUnitPlatform()                                              (7)
}
1 应用 application 插件以添加构建 Java CLI 应用的支持。
2 使用 Maven Central 来解析依赖项。
3 使用 JUnit Jupiter 进行测试(使用版本目录)。
4 应用使用了此依赖项(通过版本目录引用)。
5 定义工具链版本。
6 定义应用的主类。
7 使用 JUnit Platform 进行单元测试。

app 子项目目录中的构建脚本声明了 app 代码进行组装和测试所需的依赖项。

步骤 4:查看代码

文件 app/src/main/java/authoring/tutorial/App.java 包含项目的主类:

App.java
package authoring.tutorial;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}

代码打印一个简单的“Hello World”问候语到屏幕上。

测试类位于 app/src/test/java/authoring/tutorial/AppTest.java

AppTest.java
package authoring.tutorial;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class AppTest {
    @Test void appHasAGreeting() {
        App classUnderTest = new App();
        assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
    }
}

生成的测试类包含一个 JUnit Jupiter 测试。该测试实例化 App 类,调用其方法,并检查返回值是否符合预期。

步骤 5:运行应用

Application 插件(由 gradle init 自动添加)有助于创建可执行的 JVM 应用:

plugins {
    id("application")
}
plugins {
    id 'application'
}

应用 Application 插件会隐式应用 Java 插件,并为我们的项目添加诸如 assemblebuildrun 之类的任务。

得益于 application 插件,你可以直接从命令行运行应用。run 任务会告诉 Gradle 执行分配给 mainClass 属性的类中的 main 方法。

$ ./gradlew run

> Task :app:run
Hello World!

BUILD SUCCESSFUL in 998ms
2 actionable tasks: 2 executed

步骤 6:打包应用

application 插件会为你打包应用及其所有依赖项。生成的归档文件还将包含一个用于通过单个命令启动应用的脚本。

运行 ./gradlew build

$ ./gradlew build

> Task :app:compileJava
> Task :app:processResources NO-SOURCE
> Task :app:classes
> Task :app:jar
> Task :app:startScripts
> Task :app:distTar
> Task :app:distZip
> Task :app:assemble
> Task :app:compileTestJava
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses
> Task :app:test
> Task :app:check
> Task :app:build

BUILD SUCCESSFUL in 5s

如上所示,如果你运行一个完整构建,Gradle 将生成两种格式的归档文件:app/build/distributions/app.tarapp/build/distributions/app.zip

步骤 6:发布构建扫描

了解构建在幕后做了哪些操作的最佳方法是发布构建扫描。为此,再次使用 --scan 标志运行 build 任务。

$ ./gradlew build --scan
> Task :app:compileJava UP-TO-DATE
> Task :app:processResources NO-SOURCE
> Task :app:classes UP-TO-DATE
> Task :app:jar UP-TO-DATE
> Task :app:startScripts UP-TO-DATE
> Task :app:distTar UP-TO-DATE
> Task :app:distZip UP-TO-DATE
> Task :app:assemble UP-TO-DATE
> Task :app:compileTestJava UP-TO-DATE
> Task :app:processTestResources NO-SOURCE
> Task :app:testClasses UP-TO-DATE
> Task :app:test UP-TO-DATE
> Task :app:check UP-TO-DATE
> Task :app:build UP-TO-DATE

BUILD SUCCESSFUL in 1s
7 actionable tasks: 7 up-to-date
Resolving local hostname is slow, see https://gradle.com/help/gradle-slow-host-name

Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service. Do you accept these terms? [yes, no] yes

Gradle Terms of Service accepted.

Publishing build scan...
https://gradle.com/s/link

点击链接查看执行了哪些任务、下载了哪些依赖项以及更多细节

build scan 3

下一步:构建生命周期 >>