Spring Boot 与 Docker
观察 GraphQL 的实际运行

本指南将指导你使用 Gradle 构建一个简单的 Java 项目。

你要建造什么

你将创建一个简单的应用,并使用 Gradle 进行构建。

所需内容

  • 大约 15 分钟

  • 一个常用的文本编辑器或 IDE

  • JDK 6 或以上版本

如何完成本指南

和大多数 Spring 入门指南一样,你可以从零开始并完成每一步,也可以跳过已熟悉的基本设置步骤。不管选择哪种方式,你最终都能获得可运行的代码。

要从零开始,请继续前往设置项目

若要跳过基础知识,请执行以下操作:

完成之后,你可以将你的结果与 gs-gradle/complete 中的代码进行对比。

设置项目

首先,为 Gradle 设置一个 Java 项目。为了专注于 Gradle,现在尽量让项目保持简洁。

创建目录结构

在你选择的项目目录中创建以下子目录结构;例如,在*nix系统上可以使用mkdir -p src/main/java/hello命令:

└── src
    └── main
        └── java
            └── hello

src/main/java/hello 目录中,你可以创建任何所需的 Java 类。为了简单起见,并与本教程的其他部分保持一致,Spring 建议你创建两个类: HelloWorld.javaGreeter.java

src/main/java/hello/HelloWorld.java

package hello;

public class HelloWorld {
  public static void main(String[] args) {
  Greeter greeter = new Greeter();
  System.out.println(greeter.sayHello());
  }
}

src/main/java/hello/Greeter.java

package hello;

public class Greeter {
  public String sayHello() {
  return "Hello world!";
  }
}

安装 Gradle

你现在有一个可以使用 Gradle 构建的项目,接下来就可以安装 Gradle了。

强烈建议使用安装程序:

作为最后的手段,如果你的需求无法通过上述工具满足,你可以从 https://www.gradle.org/downloads 下载二进制文件。只需下载 gradle-version-bin.zip 文件。(你也可以选择 gradle-version-all.zip 来获取源代码和文档,以及二进制文件。)

将文件解压到您的计算机上,并将 bin 文件夹添加到系统路径中。

要测试 Gradle 的安装,请从命令行运行 Gradle:

gradle

如果一切顺利,你将会看到一条欢迎消息:

:help

Welcome to Gradle 6.0.1.

To run a build, run gradle <task> ...

To see a list of available tasks, run gradle tasks

To see a list of command-line options, run gradle --help

To see more detail about a task, run gradle help --task <task>

For troubleshooting, visit https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 455ms
1 actionable task: 1 executed

你现在已经安装了 Gradle。

探索Gradle的功能

现在 Gradle 已经安装好了,让我们看看它的功能吧。在你还未为项目创建 build.gradle 文件的情况下,可以先查看一下有哪些可用的任务。

gradle tasks

你应该会看到一个可用任务的列表。如果在没有 build.gradle 文件的文件夹中运行 Gradle,你会看到一些基本的任务,例如:

:tasks

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'gs-gradle'.
components - Displays the components produced by root project 'gs-gradle'. [incubating]
dependencies - Displays all dependencies declared in root project 'gs-gradle'.
dependencyInsight - Displays the insight into a specific dependency in root project 'gs-gradle'.
dependentComponents - Displays the dependent components of components in root project 'gs-gradle'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'gs-gradle'. [incubating]
outgoingVariants - Displays the outgoing variants of root project 'gs-gradle'.
projects - Displays the sub-projects of root project 'gs-gradle'.
properties - Displays the properties of root project 'gs-gradle'.
tasks - Displays the tasks runnable from root project 'gs-gradle'.

To see all tasks and more detail, run gradle tasks --all

To see more detail about a task, run gradle help --task <task>

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.0.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 477ms
1 actionable task: 1 executed

尽管这些任务可用,但如果没有项目构建配置,它们的价值有限。随着你完善 build.gradle 文件,某些任务会变得更加有用。当你在 build.gradle 中添加插件时,任务列表将会增长,因此你需要偶尔再次运行 tasks 来查看可用的任务。

谈到添加插件,接下来你要添加一个支持基本Java构建功能的插件。

编写Java代码

从简单开始,在你之前创建的 <项目文件夹> 中创建一个非常基本的 build.gradle 文件,并在其中添加以下内容:

apply plugin: 'java'

构建配置中的这一行带来了强大的功能。再次运行 gradle tasks,你会发现列表中新添了许多任务,比如构建项目、生成 JavaDoc 和执行测试等。

你将会经常使用gradle build任务。这个任务会编译、测试并把代码打包成一个JAR文件。你可以按照以下方式来运行它:

gradle build

几秒钟后,出现 "BUILD SUCCESSFUL" 表示构建已完成。

要查看构建结果,请查看 build 文件夹。在里面你会发现几个目录,包括以下几个值得关注的文件夹:

  • classes. 项目编译生成的 .class 文件。

  • reports. 构建过程中生成的各种报告,例如测试报告。

  • libs. 项目的组装库(通常是 JAR 和/或 WAR 文件)。

classes 文件夹包含了从编译 Java 代码生成的 .class 文件。具体来说,你应该能找到 HelloWorld.class 和 Greeter.class 这两个文件。

此时,该项目没有任何库依赖项,所以dependency_cache 文件夹是空的。

reports 文件夹应包含项目的单元测试报告。但由于当前项目尚未进行任何单元测试,这份报告会显得比较乏味。

libs 文件夹应包含一个与项目文件夹同名的 JAR 文件。稍后,你将了解如何指定 JAR 文件的名称和版本。

声明依赖项

简单的Hello World示例是完全自包含的,不需要任何额外的库。然而,大多数应用程序会依赖外部库来处理常见和/或复杂的功能。

例如,除了显示 "Hello World!" 之外,你还可以让应用程序打印当前的日期和时间。虽然可以使用 Java 原生库中的日期和时间功能,但是使用 Joda Time 库可以使这个过程更加有趣。

首先,将 HelloWorld.java 修改成以下内容:

package hello;

import org.joda.time.LocalTime;

public class HelloWorld {
  public static void main(String[] args) {
    LocalTime currentTime = new LocalTime();
    System.out.println("The current local time is: " + currentTime);

    Greeter greeter = new Greeter();
    System.out.println(greeter.sayHello());
  }
}

在这里,HelloWorld 使用 Joda Time 的 LocalTime 类来获取和打印当前时间。

如果你现在运行 gradle build 来构建项目,构建将会失败,因为你在构建文件中没有声明 Joda Time 作为编译依赖项。

首先,你需要添加一个第三方库的源。

repositories { 
    mavenCentral() 
}

repositories 块中,构建会从 Maven 中央仓库解析其依赖项。Gradle 在很大程度上借鉴了 Maven 构建工具建立的许多约定和设施,其中包括使用 Maven 中央仓库作为库依赖项来源。

现在我们已经准备好使用第三方库了,让我们来声明一些。

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    implementation "joda-time:joda-time:2.2"
    testImplementation "junit:junit:4.12"
}

dependencies 块中,你声明了对 Joda Time 的一个单一依赖。具体来说,你在请求 joda-time 组中版本为 2.2 的 joda-time 库。

需要指出的是,这是一个 compile 依赖项,在编译期间应该可以使用它(如果生成的是 WAR 文件,那么该文件会被包含到 WAR 中的 /WEB-INF/libs 目录下)。此外,还有其他值得注意的依赖类型:

  • implementation。这是编译项目代码所需的依赖项,但这些依赖项在运行时会由运行代码的容器提供(例如 Java Servlet API)。

  • testImplementation:用于编译和运行测试的依赖项,但并非构建或运行项目运行时代码所需的。

最后,让我们为我们的 JAR 构件指定一个名称。

jar {
    archiveBaseName = 'gs-gradle'
    archiveVersion =  '0.1.0'
}

jar 块定义了 JAR 文件的命名规则。在这种情况下,生成的文件名为 gs-gradle-0.1.0.jar

现在如果你运行 gradle build,Gradle 将会从 Maven 中央仓库解析 Joda Time 依赖,并成功完成构建。

使用 Gradle Wrapper 构建您的项目

Gradle Wrapper 是启动 Gradle 构建的首选方式。它包含一个用于 Windows 的批处理脚本和一个用于 OS X 和 Linux 的 shell 脚本。这些脚本允许你在没有安装 Gradle 的情况下运行 Gradle 构建。过去需要将相关配置添加到构建文件中,但现在这部分功能已经集成到了 Gradle 中,因此不再需要这样做。取而代之的是,你只需使用以下命令。

$ gradle wrapper --gradle-version 6.0.1

完成此任务后,你会发现一些新文件。两个脚本位于文件夹的根目录,而wrapper jar和属性文件则被添加到了新的gradle/wrapper 文件夹中。

└── <project folder>
    └── gradlew
    └── gradlew.bat
    └── gradle
        └── wrapper
            └── gradle-wrapper.jar
            └── gradle-wrapper.properties

现在可以使用 Gradle Wrapper 来构建你的项目了。将其添加到版本控制系统中,这样克隆你项目的每个人都可以用同样的方式来构建它。你可以像使用安装好的 Gradle 版本一样使用它。运行 wrapper 脚本来执行构建任务,就像之前那样:

./gradlew build

当你第一次运行指定版本的 Gradle 包装器时,它会下载并缓存该版本的 Gradle 二进制文件。Gradle Wrapper 文件被设计为提交到源代码控制中,这样任何人都可以无需先安装和配置特定版本的 Gradle 来构建项目。

此时,您已经完成了代码的编写。您可以在这里查看结果:

build
├── classes
│   └── main
│       └── hello
│           ├── Greeter.class
│           └── HelloWorld.class
├── dependency-cache
├── libs
│   └── gs-gradle-0.1.0.jar
└── tmp
    └── jar
        └── MANIFEST.MF

包含了GreeterHelloWorld这两个预期的类文件,以及一个JAR文件。可以快速看一下:

$ jar tvf build/libs/gs-gradle-0.1.0.jar
  0 Fri May 30 16:02:32 CDT 2014 META-INF/
 25 Fri May 30 16:02:32 CDT 2014 META-INF/MANIFEST.MF
  0 Fri May 30 16:02:32 CDT 2014 hello/
369 Fri May 30 16:02:32 CDT 2014 hello/Greeter.class
988 Fri May 30 16:02:32 CDT 2014 hello/HelloWorld.class

类文件已被打包在一起。值得注意的是,尽管你已将 joda-time 声明为依赖项,但该库并未被包含进来。此外,JAR 文件也无法直接运行。

要使这段代码可运行,你可以使用 gradle 的 application 插件,并将其添加到你的 build.gradle 文件中。

apply plugin: 'application'

mainClassName = 'hello.HelloWorld'

然后你可以运行应用了!

$ ./gradlew run
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:run
The current local time is: 16:16:20.544
Hello world!

BUILD SUCCESSFUL

Total time: 3.798 secs

打包依赖项需要更多的考虑。例如,如果我们正在构建一个 WAR 文件(这种格式通常用于包含第三方依赖项),我们可以使用 gradle 的 WAR 插件。如果你在使用 Spring Boot 并且想要生成一个可执行的 JAR 文件,spring-boot-gradle-plugin 非常方便。在这个阶段,gradle 还不足以了解你的系统情况以做出选择。但目前这应该足以让你开始使用 gradle 了。

作为本指南的结尾,这里是完整的 build.gradle 文件:

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'

mainClassName = 'hello.HelloWorld'

// tag::repositories[]
repositories { 
    mavenCentral() 
}
// end::repositories[]

// tag::jar[]
jar {
    archiveBaseName = 'gs-gradle'
    archiveVersion =  '0.1.0'
}
// end::jar[]

// tag::dependencies[]
sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    implementation "joda-time:joda-time:2.2"
    testImplementation "junit:junit:4.12"
}
// end::dependencies[]

// tag::wrapper[]
// end::wrapper[]
此处嵌入了多个起始和结束注释。这样就可以将构建文件中的部分内容提取出来,并在此指南中进行详细的说明。但在你的生产构建文件中无需包含这些注释。

摘要

恭喜您!现在您已经创建了一个简单而有效的Gradle构建文件,用于构建Java项目。

参见

以下指南可能会有所帮助:

本页目录