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

本指南将引导您完成使用 Spring 调度任务的步骤。

你将构建什么

您将构建一个应用程序,该程序通过使用 Spring Framework 的 @Scheduled 注解每五秒钟打印一次当前时间。

所需条件

  • 大约15分钟

  • 一个喜欢的文本编辑器或IDE

  • Java 17 或更高版本

如何完成本指南

与大多数 Spring 入门指南 一样,您可以从头开始并完成每个步骤,或者通过查看 此仓库 中的代码直接跳到解决方案。

要在本地环境中查看最终结果,您可以执行以下操作之一:

从 Spring Initializr 开始

您可以使用这个预初始化项目,然后点击生成以下载一个 ZIP 文件。该项目已配置为适合本指南中的示例。

要手动初始化项目:

  1. 访问 https://start.spring.io。该服务会拉取应用程序所需的所有依赖项,并为您完成大部分设置工作。

  2. 选择 Gradle 或 Maven 以及您想要使用的语言。本指南假设您选择了 Java 和 Gradle。

  3. 点击 Generate

  4. 下载生成的 ZIP 文件,这是一个根据您的选择配置好的应用程序存档。

如果您的 IDE 集成了 Spring Initializr,您可以直接在 IDE 中完成此过程。

启用调度

虽然可以将定时任务嵌入到 web 应用程序中,但更简单的方法(如本指南所示)是创建一个独立的应用程序。为此,将所有内容打包到一个可执行的 JAR 文件中,并通过 Java 的 main() 方法来驱动。以下代码片段(来自 src/main/java/com/example/schedulingtasks/SchedulingTasksApplication.java)展示了应用程序类:

@SpringBootApplication
@EnableScheduling
public class SchedulingTasksApplication {

Spring Initializr 在我们的主类中添加了 @SpringBootApplication 注解。@SpringBootApplication 是一个便捷的注解,它添加了以下所有内容:

  • @Configuration: 将该类标记为应用程序上下文的bean定义源。

  • @EnableAutoConfiguration: Spring Boot 根据您添加的依赖项尝试自动配置您的 Spring 应用程序。

  • @ComponentScan: 告诉 Spring 去查找其他组件、配置和服务。如果没有定义特定的包,递归扫描将从声明该注解的类所在的包开始。

此外,添加 @EnableScheduling 注解。该注解启用了 Spring 的定时任务执行功能。

创建计划任务

创建一个名为 src/main/java/com/example/schedulingtasks/ScheduledTasks.java 的新类:

@Component
public class ScheduledTasks {

    private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        log.info("The time is now {}", dateFormat.format(new Date()));
    }
}

Scheduled 注解 定义了特定方法的执行时间。

本示例使用了 [fixedRate()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#fixedRate(),它指定了方法调用之间的间隔,从每次调用的开始时间开始计算。其他选项包括 [cron()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#cron() 和 [fixedDelay()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#fixedDelay()。对于周期性任务,必须指定这三种选项中的一种,并且可以选择性地指定 [initialDelay()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#initialDelay()。对于一次性任务,只需指定一个 initialDelay() 即可。

运行应用程序

现在,您应该能够通过执行 SchedulingTasksApplication 中的主方法来运行应用程序。您可以从 IDE 中运行该程序,也可以在项目根目录下执行以下 Gradle 命令:

./gradlew bootRun

这样做会启动应用程序,并且带有 @Scheduled 注解的方法会运行。您应该会看到类似于以下的日志消息:

20yy-mm-ddT07:23:01.665-04:00  INFO 19633 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 07:23:01
20yy-mm-ddT07:23:06.663-04:00  INFO 19633 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 07:23:06
20yy-mm-ddT07:23:11.663-04:00  INFO 19633 --- [   scheduling-1] c.e.schedulingtasks.ScheduledTasks       : The time is now 07:23:11

此示例使用 [fixedRate()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/Scheduled.html#fixedRate() 调度,因此应用程序将无限期运行,直到您手动中断它。

使用 awaitility 依赖进行测试

为了正确测试您的应用程序,您可以使用 awaitility。自 Spring Boot 3.2 起,这是一个由 Boot 管理的依赖项。您可以在 src/test/java/com/example/schedulingtasks/ScheduledTasksTest.java 中创建新测试或查看现有测试:

@SpringBootTest
public class ScheduledTasksTest {

    @SpyBean
    ScheduledTasks tasks;

    @Test
    public void reportCurrentTime() {
        await().atMost(Durations.TEN_SECONDS).untilAsserted(() -> {
            verify(tasks, atLeast(2)).reportCurrentTime();
        });
    }
}

当您运行 ./gradlew clean build 任务时,此测试会自动执行。

构建应用程序

本节介绍了运行本指南的不同方式:

  1. 构建并执行 JAR 文件

  2. 使用 Cloud Native Buildpacks 构建并执行 Docker 容器

  3. 构建并执行原生镜像

  4. 使用 Cloud Native Buildpacks 构建并执行原生镜像容器

无论您选择如何运行应用程序,输出结果都应该是一样的。

要运行该应用程序,您可以将其打包为可执行的 jar 文件。./gradlew clean build 命令会将应用程序编译为可执行的 jar 文件。然后,您可以使用 java -jar build/libs/gs-scheduling-tasks-0.0.1-SNAPSHOT.jar 命令来运行该 jar 文件。

或者,如果您有一个可用的 Docker 环境,您可以直接使用 buildpacks 从 Maven 或 Gradle 插件创建 Docker 镜像。通过 Cloud Native Buildpacks,您可以创建可以在任何地方运行的 Docker 兼容镜像。Spring Boot 直接为 Maven 和 Gradle 提供了 buildpack 支持。这意味着您可以输入一条命令,并快速将合理的镜像推送到本地运行的 Docker 守护程序中。要使用 Cloud Native Buildpacks 创建 Docker 镜像,请运行 ./gradlew bootBuildImage 命令。在启用 Docker 环境的情况下,您可以使用 docker run docker.io/library/gs-scheduling-tasks:0.0.1-SNAPSHOT 命令来运行该应用程序。

原生镜像支持

Spring Boot 还支持编译为原生镜像,前提是您的机器上安装了 GraalVM 发行版。要使用 Native Build Tools 通过 Gradle 创建原生镜像,首先确保您的 Gradle 构建中包含一个 plugins 块,其中包含 org.graalvm.buildtools.native

plugins {
    id 'org.graalvm.buildtools.native' version '0.9.28'
...

您可以运行 ./gradlew nativeCompile 命令来生成原生镜像。当构建完成后,您可以通过执行 build/native/nativeCompile/gs-scheduling-tasks 命令来运行代码,并且启动时间几乎瞬时。

您也可以使用 Buildpacks 创建原生镜像。通过运行 ./gradlew bootBuildImage 命令,您可以生成原生镜像。构建完成后,您可以使用 docker run docker.io/library/gs-scheduling-tasks:0.0.1-SNAPSHOT 命令启动应用程序。

总结

恭喜!您已成功创建了一个包含定时任务的应用程序。

另请参阅

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

本页目录