Gradle 构建生命周期中的初始化阶段,会使用设置文件在您的项目根目录中查找根项目和包含的子项目。

author gradle 6

然后,对于设置文件中包含的每个项目,Gradle 都会创建一个 Project 实例。

然后,Gradle 会查找相应的构建脚本文件,该文件在配置阶段中使用。

构建脚本

每个 Gradle 构建都包含一个或多个项目;一个项目和多个子项目

项目通常对应于需要构建的软件组件,例如库或应用程序。它可能代表一个库 JAR、一个 Web 应用程序,或者一个由其他项目生成的 JAR 组装而成的发行 ZIP。

另一方面,它可能代表需要完成的事情,例如将您的应用程序部署到测试或生产环境。

Gradle 脚本可以使用 Groovy DSL 或 Kotlin DSL(领域特定语言)编写。

构建脚本配置一个项目,并与类型为 Project 的对象关联。

Build

当构建脚本执行时,它会配置 Project

构建脚本可以是 Groovy 的 *.gradle 文件,也可以是 Kotlin 的 *.gradle.kts 文件。

构建脚本配置 Project 对象及其子对象。

Project 对象

Project 对象是 Gradle API 的一部分

  • 在 Groovy DSL 中,Project 对象的文档可在此处找到。

  • 在 Kotlin DSL 中,Project 对象的文档可在此处找到。

构建脚本中的许多顶级属性和块都是 Project API 的一部分。

例如,以下构建脚本使用 Project.name 属性打印项目的名称

build.gradle.kts
println(name)
println(project.name)
build.gradle
println name
println project.name
$ gradle -q check
project-api
project-api

这两个 println 语句都打印相同的属性。

第一个语句使用对 Project 对象的 name 属性的顶级引用。第二个语句使用任何构建脚本都可用的 project 属性,该属性返回关联的 Project 对象。

标准项目属性

Project 对象在您的构建脚本中公开了一组标准属性。

下表列出了一些常用属性

名称 类型 描述

name

String

项目目录的名称。

path

String

项目的完全限定名称。

description

String

项目的描述。

dependencies

DependencyHandler

返回项目的依赖项处理器。

repositories

RepositoryHandler

返回项目的仓库处理器。

layout

ProjectLayout

提供对项目几个重要位置的访问。

group

Object

该项目的组。

version

Object

该项目的版本。

下表列出了一些常用方法

名称 描述

uri()

将文件路径解析为 URI,相对于此项目的项目目录。

task()

创建具有给定名称的任务并将其添加到此项目。

构建脚本结构

构建脚本由 { …​ } 组成,这是 Groovy 和 Kotlin 中一个特殊的对象。在 Kotlin 中,此对象称为lambda,在 Groovy 中称为闭包

简单来说,plugins{ } 块是一个方法调用,其中一个 Kotlin lambda 对象或 Groovy 闭包对象作为参数传递。它是以下形式的缩写

plugins(function() {
    id("plugin")
})

块映射到 Gradle API 方法。

函数内的代码针对一个 this 对象执行,该对象在 Kotlin lambda 中称为接收器,在 Groovy 闭包中称为委托。Gradle 确定正确的 this 对象并调用正确的相应方法。方法调用 id("plugin") 对象的 this 的类型为 PluginDependenciesSpec

构建脚本本质上由基于 DSL 构建的 Gradle API 调用组成。Gradle 逐行从上到下执行脚本。

让我们看一个例子并将其分解

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

repositories {  (2)
    mavenCentral()
}

dependencies {  (3)
    testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation("com.google.guava:guava:32.1.1-jre")
}

application {   (4)
    mainClass = "com.example.Main"
}

tasks.named<Test>("test") { (5)
    useJUnitPlatform()
}

tasks.named<Javadoc>("javadoc").configure {
    exclude("app/Internal*.java")
    exclude("app/internal/*")
}

tasks.register<Zip>("zip-reports") {
    from("Reports/")
    include("*")
    archiveFileName.set("Reports.zip")
    destinationDirectory.set(file("/dir"))
}
build.gradle
plugins {   (1)
    id 'application'
}

repositories {  (2)
    mavenCentral()
}

dependencies {  (3)
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    implementation 'com.google.guava:guava:32.1.1-jre'
}

application {   (4)
    mainClass = 'com.example.Main'
}

tasks.named('test', Test) { (5)
    useJUnitPlatform()
}

tasks.named('javadoc', Javadoc).configure {
    exclude 'app/Internal*.java'
    exclude 'app/internal/*'
}

tasks.register('zip-reports', Zip) {
    from 'Reports/'
    include '*'
    archiveFileName = 'Reports.zip'
    destinationDirectory = file('/dir')
}
1 将插件应用于构建。
2 定义可以找到依赖项的位置。
3 添加依赖项。
4 设置属性。
5 注册和配置任务。

1. 将插件应用于构建

插件用于扩展 Gradle。它们还用于模块化和重用项目配置。

可以使用 PluginDependenciesSpec 插件脚本块应用插件。

首选插件块

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

在示例中,应用了 Gradle 中包含的 application 插件,将我们的项目描述为 Java 应用程序。

2. 定义可以找到依赖项的位置

一个项目通常需要许多依赖项才能完成其工作。依赖项包括插件、库或 Gradle 必须下载才能成功构建的组件。

构建脚本让 Gradle 知道在哪里查找依赖项的二进制文件。可以提供多个位置

build.gradle.kts
repositories {  (2)
    mavenCentral()
}
build.gradle
repositories {  (2)
    mavenCentral()
}

在示例中,guava 库和 JetBrains Kotlin 插件 (org.jetbrains.kotlin.jvm) 将从 Maven Central Repository 下载。

3. 添加依赖项

一个项目通常需要许多依赖项才能完成其工作。这些依赖项通常是预编译类的库,它们被导入到项目的源代码中。

依赖项通过配置进行管理,并从仓库中检索。

使用 Project.getDependencies() 方法返回的 DependencyHandler 来管理依赖项。使用 Project.getRepositories() 方法返回的 RepositoryHandler 来管理仓库。

build.gradle.kts
dependencies {  (3)
    testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.3")
    testRuntimeOnly("org.junit.platform:junit-platform-launcher")
    implementation("com.google.guava:guava:32.1.1-jre")
}
build.gradle
dependencies {  (3)
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    implementation 'com.google.guava:guava:32.1.1-jre'
}

在示例中,应用程序代码使用 Google 的 guava 库。Guava 提供集合、缓存、基本类型支持、并发、通用注解、字符串处理、I/O 和验证的实用方法。

4. 设置属性

插件可以使用扩展向项目添加属性和方法。

Project 对象具有一个关联的 ExtensionContainer 对象,其中包含已应用于项目的所有插件的设置和属性。

在示例中,application 插件添加了一个 application 属性,用于详细说明 Java 应用程序的主类

build.gradle.kts
application {   (4)
    mainClass = "com.example.Main"
}
build.gradle
application {   (4)
    mainClass = 'com.example.Main'
}

5. 注册和配置任务

任务执行一些基本的工作,例如编译类、运行单元测试或打包 WAR 文件。

虽然任务通常在插件中定义,但您可能需要在构建脚本中注册或配置任务。

注册任务会将任务添加到您的项目中。

您可以使用 TaskContainer.register(java.lang.String) 方法在项目中注册任务

build.gradle.kts
tasks.register<Zip>("zip-reports") {
    from("Reports/")
    include("*")
    archiveFileName.set("Reports.zip")
    destinationDirectory.set(file("/dir"))
}
build.gradle
tasks.register('zip-reports', Zip) {
    from 'Reports/'
    include '*'
    archiveFileName = 'Reports.zip'
    destinationDirectory = file('/dir')
}

您可能已经见过 TaskContainer.create(java.lang.String) 方法的使用,应避免使用该方法

tasks.create<Zip>("zip-reports") { }
register() 优于 create(),它支持任务配置规避

您可以使用 TaskCollection.named(java.lang.String) 方法定位任务以对其进行配置

build.gradle.kts
tasks.named<Test>("test") { (5)
    useJUnitPlatform()
}
build.gradle
tasks.named('test', Test) { (5)
    useJUnitPlatform()
}

下面的示例配置 Javadoc 任务以自动从 Java 代码生成 HTML 文档

build.gradle.kts
tasks.named<Javadoc>("javadoc").configure {
    exclude("app/Internal*.java")
    exclude("app/internal/*")
}
build.gradle
tasks.named('javadoc', Javadoc).configure {
    exclude 'app/Internal*.java'
    exclude 'app/internal/*'
}

构建脚本编写

构建脚本由零个或多个语句和脚本块组成

println(project.layout.projectDirectory);

语句可以包括方法调用、属性赋值和局部变量定义

version = '1.0.0.GA'

脚本块是一个方法调用,它将闭包/lambda 作为参数

configurations {
}

闭包/lambda 在执行时配置一些委托对象

repositories {
    google()
}

构建脚本也是 Groovy 或 Kotlin 脚本

build.gradle.kts
tasks.register("upper") {
    doLast {
        val someString = "mY_nAmE"
        println("Original: $someString")
        println("Upper case: ${someString.uppercase()}")
    }
}
build.gradle
tasks.register('upper') {
    doLast {
        String someString = 'mY_nAmE'
        println "Original: $someString"
        println "Upper case: ${someString.toUpperCase()}"
    }
}
$ gradle -q upper
Original: mY_nAmE
Upper case: MY_NAME

它可以包含 Groovy 或 Kotlin 脚本中允许的元素,例如方法定义和类定义

build.gradle.kts
tasks.register("count") {
    doLast {
        repeat(4) { print("$it ") }
    }
}
build.gradle
tasks.register('count') {
    doLast {
        4.times { print "$it " }
    }
}
$ gradle -q count
0 1 2 3 

灵活的任务注册

利用 Groovy 或 Kotlin 语言的功能,您可以在循环中注册多个任务

build.gradle.kts
repeat(4) { counter ->
    tasks.register("task$counter") {
        doLast {
            println("I'm task number $counter")
        }
    }
}
build.gradle
4.times { counter ->
    tasks.register("task$counter") {
        doLast {
            println "I'm task number $counter"
        }
    }
}
$ gradle -q task1
I'm task number 1

Gradle 类型

在 Gradle 中,类型属性提供者是管理和配置构建逻辑的基础

  • 类型:Gradle 定义类型(如 TaskConfigurationFile 等)来表示构建组件。您可以扩展这些类型来创建自定义任务或领域对象。

  • 属性:Gradle 属性(例如 Property<T>ListProperty<T>SetProperty<T>)用于构建配置。它们允许惰性求值,这意味着它们的值仅在需要时才计算,从而提高灵活性和性能。

  • 提供者Provider<T> 表示一个惰性计算或检索的值。提供者通常与属性一起使用,以延迟值计算直到必要时。这对于将动态运行时值集成到您的构建中特别有用。

您可以在理解 Gradle 类型中了解更多信息。

声明变量

构建脚本可以声明两种变量:局部变量额外属性

局部变量

使用 val 关键字声明局部变量。局部变量仅在其声明的作用域内可见。它们是底层 Kotlin 语言的特性。

使用 def 关键字声明局部变量。局部变量仅在其声明的作用域内可见。它们是底层 Groovy 语言的特性。

build.gradle.kts
val dest = "dest"

tasks.register<Copy>("copy") {
    from("source")
    into(dest)
}
build.gradle
def dest = 'dest'

tasks.register('copy', Copy) {
    from 'source'
    into dest
}

额外属性

Gradle 的增强对象,包括项目、任务和源集,可以持有用户定义的属性。

通过拥有对象的 extra 属性添加、读取和设置额外属性。或者,您可以使用 by extra 通过 Kotlin 委托属性访问额外属性。

通过拥有对象的 ext 属性添加、读取和设置额外属性。或者,您可以使用 ext 块同时添加多个属性。

build.gradle.kts
plugins {
    id("java-library")
}

val springVersion by extra("3.1.0.RELEASE")
val emailNotification by extra { "build@master.org" }

sourceSets.all { extra["purpose"] = null }

sourceSets {
    main {
        extra["purpose"] = "production"
    }
    test {
        extra["purpose"] = "test"
    }
    create("plugin") {
        extra["purpose"] = "production"
    }
}

tasks.register("printProperties") {
    val springVersion = springVersion
    val emailNotification = emailNotification
    val productionSourceSets = provider {
        sourceSets.matching { it.extra["purpose"] == "production" }.map { it.name }
    }
    doLast {
        println(springVersion)
        println(emailNotification)
        productionSourceSets.get().forEach { println(it) }
    }
}
build.gradle
plugins {
    id 'java-library'
}

ext {
    springVersion = "3.1.0.RELEASE"
    emailNotification = "build@master.org"
}

sourceSets.all { ext.purpose = null }

sourceSets {
    main {
        purpose = "production"
    }
    test {
        purpose = "test"
    }
    plugin {
        purpose = "production"
    }
}

tasks.register('printProperties') {
    def springVersion = springVersion
    def emailNotification = emailNotification
    def productionSourceSets = provider {
        sourceSets.matching { it.purpose == "production" }.collect { it.name }
    }
    doLast {
        println springVersion
        println emailNotification
        productionSourceSets.get().each { println it }
    }
}
$ gradle -q printProperties
3.1.0.RELEASE
build@master.org
main
plugin

此示例通过 by extraproject 对象添加了两个额外属性。此外,此示例通过将 extra["purpose"] 设置为 null,向每个源集添加了一个名为 purpose 的属性。添加后,您可以通过 extra 读取和设置这些属性。

此示例通过 ext 块向 project 对象添加了两个额外属性。此外,此示例通过将 ext.purpose 设置为 null,向每个源集添加了一个名为 purpose 的属性。添加后,您可以像访问预定义属性一样读取和设置所有这些属性。

Gradle 要求添加属性时使用特殊语法,以便它可以快速失败。例如,这允许 Gradle 识别脚本何时尝试设置不存在的属性。您可以在任何可以访问其拥有对象的地方访问额外属性。这使得额外属性具有比局部变量更广泛的作用域。子项目可以访问其父项目上的额外属性。

有关额外属性的更多信息,请参阅 API 文档中的 ExtraPropertiesExtension

配置任意对象

示例 greet() 任务展示了任意对象配置的示例

build.gradle.kts
class UserInfo(
    var name: String? = null,
    var email: String? = null
)

tasks.register("greet") {
    val user = UserInfo().apply {
        name = "Isaac Newton"
        email = "isaac@newton.me"
    }
    doLast {
        println(user.name)
        println(user.email)
    }
}
build.gradle
class UserInfo {
    String name
    String email
}

tasks.register('greet') {
    def user = configure(new UserInfo()) {
        name = "Isaac Newton"
        email = "isaac@newton.me"
    }
    doLast {
        println user.name
        println user.email
    }
}
$ gradle -q greet
Isaac Newton
isaac@newton.me

闭包委托

每个闭包都有一个 delegate 对象。Groovy 使用此委托查找非局部变量和闭包参数的变量和方法引用。Gradle 将此用于配置闭包,其中 delegate 对象引用正在配置的对象。

build.gradle
dependencies {
    assert delegate == project.dependencies
    testImplementation('junit:junit:4.13')
    delegate.testImplementation('junit:junit:4.13')
}

默认导入

为了使构建脚本更简洁,Gradle 会自动向脚本添加一组导入语句。

因此,您可以将 throw new org.gradle.api.tasks.StopExecutionException() 替换为 throw new StopExecutionException()

Gradle 隐式地将以下导入添加到每个脚本中

import org.gradle.*
import org.gradle.api.*
import org.gradle.api.artifacts.*
import org.gradle.api.artifacts.capability.*
import org.gradle.api.artifacts.component.*
import org.gradle.api.artifacts.dsl.*
import org.gradle.api.artifacts.ivy.*
import org.gradle.api.artifacts.maven.*
import org.gradle.api.artifacts.query.*
import org.gradle.api.artifacts.repositories.*
import org.gradle.api.artifacts.result.*
import org.gradle.api.artifacts.transform.*
import org.gradle.api.artifacts.type.*
import org.gradle.api.artifacts.verification.*
import org.gradle.api.attributes.*
import org.gradle.api.attributes.java.*
import org.gradle.api.attributes.plugin.*
import org.gradle.api.cache.*
import org.gradle.api.capabilities.*
import org.gradle.api.component.*
import org.gradle.api.configuration.*
import org.gradle.api.credentials.*
import org.gradle.api.distribution.*
import org.gradle.api.distribution.plugins.*
import org.gradle.api.execution.*
import org.gradle.api.file.*
import org.gradle.api.flow.*
import org.gradle.api.initialization.*
import org.gradle.api.initialization.definition.*
import org.gradle.api.initialization.dsl.*
import org.gradle.api.initialization.resolve.*
import org.gradle.api.invocation.*
import org.gradle.api.java.archives.*
import org.gradle.api.jvm.*
import org.gradle.api.launcher.cli.*
import org.gradle.api.logging.*
import org.gradle.api.logging.configuration.*
import org.gradle.api.model.*
import org.gradle.api.plugins.*
import org.gradle.api.plugins.antlr.*
import org.gradle.api.plugins.catalog.*
import org.gradle.api.plugins.jvm.*
import org.gradle.api.plugins.quality.*
import org.gradle.api.plugins.scala.*
import org.gradle.api.problems.*
import org.gradle.api.project.*
import org.gradle.api.provider.*
import org.gradle.api.publish.*
import org.gradle.api.publish.ivy.*
import org.gradle.api.publish.ivy.plugins.*
import org.gradle.api.publish.ivy.tasks.*
import org.gradle.api.publish.maven.*
import org.gradle.api.publish.maven.plugins.*
import org.gradle.api.publish.maven.tasks.*
import org.gradle.api.publish.plugins.*
import org.gradle.api.publish.tasks.*
import org.gradle.api.reflect.*
import org.gradle.api.reporting.*
import org.gradle.api.reporting.components.*
import org.gradle.api.reporting.dependencies.*
import org.gradle.api.reporting.dependents.*
import org.gradle.api.reporting.model.*
import org.gradle.api.reporting.plugins.*
import org.gradle.api.resources.*
import org.gradle.api.services.*
import org.gradle.api.specs.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.ant.*
import org.gradle.api.tasks.application.*
import org.gradle.api.tasks.bundling.*
import org.gradle.api.tasks.compile.*
import org.gradle.api.tasks.diagnostics.*
import org.gradle.api.tasks.diagnostics.artifact.transforms.*
import org.gradle.api.tasks.diagnostics.configurations.*
import org.gradle.api.tasks.incremental.*
import org.gradle.api.tasks.javadoc.*
import org.gradle.api.tasks.options.*
import org.gradle.api.tasks.scala.*
import org.gradle.api.tasks.testing.*
import org.gradle.api.tasks.testing.junit.*
import org.gradle.api.tasks.testing.junitplatform.*
import org.gradle.api.tasks.testing.testng.*
import org.gradle.api.tasks.util.*
import org.gradle.api.tasks.wrapper.*
import org.gradle.api.toolchain.management.*
import org.gradle.authentication.*
import org.gradle.authentication.aws.*
import org.gradle.authentication.http.*
import org.gradle.build.event.*
import org.gradle.buildconfiguration.tasks.*
import org.gradle.buildinit.*
import org.gradle.buildinit.plugins.*
import org.gradle.buildinit.specs.*
import org.gradle.buildinit.tasks.*
import org.gradle.caching.*
import org.gradle.caching.configuration.*
import org.gradle.caching.http.*
import org.gradle.caching.local.*
import org.gradle.concurrent.*
import org.gradle.external.javadoc.*
import org.gradle.ide.visualstudio.*
import org.gradle.ide.visualstudio.plugins.*
import org.gradle.ide.visualstudio.tasks.*
import org.gradle.ide.xcode.*
import org.gradle.ide.xcode.plugins.*
import org.gradle.ide.xcode.tasks.*
import org.gradle.ivy.*
import org.gradle.jvm.*
import org.gradle.jvm.application.scripts.*
import org.gradle.jvm.application.tasks.*
import org.gradle.jvm.tasks.*
import org.gradle.jvm.toolchain.*
import org.gradle.language.*
import org.gradle.language.assembler.*
import org.gradle.language.assembler.plugins.*
import org.gradle.language.assembler.tasks.*
import org.gradle.language.base.*
import org.gradle.language.base.artifact.*
import org.gradle.language.base.compile.*
import org.gradle.language.base.plugins.*
import org.gradle.language.base.sources.*
import org.gradle.language.c.*
import org.gradle.language.c.plugins.*
import org.gradle.language.c.tasks.*
import org.gradle.language.cpp.*
import org.gradle.language.cpp.plugins.*
import org.gradle.language.cpp.tasks.*
import org.gradle.language.java.artifact.*
import org.gradle.language.jvm.tasks.*
import org.gradle.language.nativeplatform.*
import org.gradle.language.nativeplatform.tasks.*
import org.gradle.language.objectivec.*
import org.gradle.language.objectivec.plugins.*
import org.gradle.language.objectivec.tasks.*
import org.gradle.language.objectivecpp.*
import org.gradle.language.objectivecpp.plugins.*
import org.gradle.language.objectivecpp.tasks.*
import org.gradle.language.plugins.*
import org.gradle.language.rc.*
import org.gradle.language.rc.plugins.*
import org.gradle.language.rc.tasks.*
import org.gradle.language.scala.tasks.*
import org.gradle.language.swift.*
import org.gradle.language.swift.plugins.*
import org.gradle.language.swift.tasks.*
import org.gradle.maven.*
import org.gradle.model.*
import org.gradle.nativeplatform.*
import org.gradle.nativeplatform.platform.*
import org.gradle.nativeplatform.plugins.*
import org.gradle.nativeplatform.tasks.*
import org.gradle.nativeplatform.test.*
import org.gradle.nativeplatform.test.cpp.*
import org.gradle.nativeplatform.test.cpp.plugins.*
import org.gradle.nativeplatform.test.cunit.*
import org.gradle.nativeplatform.test.cunit.plugins.*
import org.gradle.nativeplatform.test.cunit.tasks.*
import org.gradle.nativeplatform.test.googletest.*
import org.gradle.nativeplatform.test.googletest.plugins.*
import org.gradle.nativeplatform.test.plugins.*
import org.gradle.nativeplatform.test.tasks.*
import org.gradle.nativeplatform.test.xctest.*
import org.gradle.nativeplatform.test.xctest.plugins.*
import org.gradle.nativeplatform.test.xctest.tasks.*
import org.gradle.nativeplatform.toolchain.*
import org.gradle.nativeplatform.toolchain.plugins.*
import org.gradle.normalization.*
import org.gradle.platform.*
import org.gradle.platform.base.*
import org.gradle.platform.base.binary.*
import org.gradle.platform.base.component.*
import org.gradle.platform.base.plugins.*
import org.gradle.plugin.devel.*
import org.gradle.plugin.devel.plugins.*
import org.gradle.plugin.devel.tasks.*
import org.gradle.plugin.management.*
import org.gradle.plugin.use.*
import org.gradle.plugins.ear.*
import org.gradle.plugins.ear.descriptor.*
import org.gradle.plugins.ide.*
import org.gradle.plugins.ide.api.*
import org.gradle.plugins.ide.eclipse.*
import org.gradle.plugins.ide.idea.*
import org.gradle.plugins.signing.*
import org.gradle.plugins.signing.signatory.*
import org.gradle.plugins.signing.signatory.pgp.*
import org.gradle.plugins.signing.type.*
import org.gradle.plugins.signing.type.pgp.*
import org.gradle.process.*
import org.gradle.swiftpm.*
import org.gradle.swiftpm.plugins.*
import org.gradle.swiftpm.tasks.*
import org.gradle.testing.base.*
import org.gradle.testing.base.plugins.*
import org.gradle.testing.jacoco.plugins.*
import org.gradle.testing.jacoco.tasks.*
import org.gradle.testing.jacoco.tasks.rules.*
import org.gradle.testkit.runner.*
import org.gradle.util.*
import org.gradle.vcs.*
import org.gradle.vcs.git.*
import org.gradle.work.*
import org.gradle.workers.*

此外,对于 Groovy,还添加了以下导入

import java.lang.*
import java.io.*
import java.net.*
import java.util.*
import java.time.*
import java.math.BigDecimal
import java.math.BigInteger
import javax.inject.Inject

下一步: 了解如何使用任务 >>