编辑此页面

Spring Scheduling API 的 Quarkus 扩展

虽然鼓励用户使用 标准的 Quarkus 调度器,但 Quarkus 以 spring-scheduled 扩展的形式提供了一个 Spring Scheduled 的兼容层。

本指南将解释 Quarkus 应用程序如何利用大家熟知的 Spring Scheduled 注解来配置和调度任务。

先决条件

要完成本指南,您需要

  • 大约 15 分钟

  • 一个 IDE

  • 已安装 JDK 17+ 并正确配置了 JAVA_HOME

  • Apache Maven 3.9.9

  • 如果您想使用它,可以选择 Quarkus CLI

  • 如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置

  • 对 Spring Web 扩展有一定的了解

解决方案

我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。

克隆 Git 存储库:git clone https://github.com/quarkusio/quarkus-quickstarts.git,或者下载一个 存档

解决方案位于 spring-scheduled-quickstart 目录

创建 Maven 项目

首先,我们需要一个新项目。使用以下命令创建一个新项目

命令行界面
quarkus create app org.acme:spring-scheduler-quickstart \
    --extension='rest,spring-scheduled' \
    --no-code
cd spring-scheduler-quickstart

要创建 Gradle 项目,请添加 --gradle--gradle-kotlin-dsl 选项。

有关如何安装和使用 Quarkus CLI 的更多信息,请参阅 Quarkus CLI 指南。

Maven
mvn io.quarkus.platform:quarkus-maven-plugin:3.24.4:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-scheduler-quickstart \
    -Dextensions='rest,spring-scheduled' \
    -DnoCode
cd spring-scheduler-quickstart

要创建 Gradle 项目,请添加 -DbuildTool=gradle-DbuildTool=gradle-kotlin-dsl 选项。

对于 Windows 用户

  • 如果使用 cmd,(不要使用反斜杠 \ 并将所有内容放在同一行上)

  • 如果使用 Powershell,请将 -D 参数用双引号括起来,例如 "-DprojectArtifactId=spring-scheduler-quickstart"

此命令将生成一个包含 spring-scheduled 扩展的 Maven 项目。

如果您已经配置了 Quarkus 项目,可以在项目根目录下运行以下命令将 spring-scheduled 扩展添加到您的项目中

命令行界面
quarkus extension add spring-scheduled
Maven
./mvnw quarkus:add-extension -Dextensions='spring-scheduled'
Gradle
./gradlew addExtension --extensions='spring-scheduled'

这会将以下内容添加到您的构建文件中

pom.xml
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-spring-scheduled</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-spring-scheduled")

创建计划任务

org.acme.spring.scheduler 包中,创建 CounterBean 类,内容如下

package org.acme.spring.scheduler;

import org.springframework.scheduling.annotation.Scheduled;

import java.util.concurrent.atomic.AtomicInteger;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped              (1)
public class CounterBean {

    private AtomicInteger counter = new AtomicInteger();

    public int get() {   (2)
        return counter.get();
    }

    @Scheduled(cron="*/5 * * * * ?")   (3)
    void cronJob() {
        counter.incrementAndGet();      (4)
        System.out.println("Cron expression hardcoded");
    }

    @Scheduled(cron = "{cron.expr}")   (5)
    void cronJobWithExpressionInConfig() {
        counter.incrementAndGet();
        System.out.println("Cron expression configured in application.properties");
    }

    @Scheduled(fixedRate = 1000)    (6)
    void jobAtFixedRate() {
        counter.incrementAndGet();
        System.out.println("Fixed Rate expression");
    }

    @Scheduled(fixedRateString = "${fixedRate.expr}")      (7)
    void jobAtFixedRateInConfig() {
        counter.incrementAndGet();
        System.out.println("Fixed Rate expression configured in application.properties");
    }
}
1 在 *application* 作用域中声明 bean。Spring 仅检测 bean 中的 @Scheduled 注解。
2 get() 方法允许检索当前值。
3 使用 Spring 的 @Scheduled 注解和一个类 cron 表达式来指示 Quarkus 调度此方法的执行。在此示例中,我们计划每天上午 10:15 执行任务。
4 代码非常直观。每天上午 10:15,计数器会递增。
5 使用类 cron 表达式 cron.expr 定义一个任务,该表达式可在 application.properties 中配置。
6 定义一个以固定时间间隔执行的方法。时间间隔以毫秒为单位。
7 使用类 cron 表达式 fixedRate.expr 定义一个任务,该表达式可在 application.properties 中配置。

更新应用程序配置文件

编辑 application.properties 文件并添加 cron.exprfixedRate.expr 配置

# The syntax used by Spring for cron expressions is the same as which is used by regular Quarkus scheduler.
cron.expr=*/5 * * * * ?
fixedRate.expr=1000

创建资源和测试

创建 CountResource 类,内容如下

package org.acme.spring.scheduler;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/count")
public class CountResource {

    @Inject
    CounterBean counter;    (1)


    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String hello() {
        return "count: " + counter.get();   (2)
    }
}
1 注入 CounterBean
2 返回当前的计数器值

我们还需要更新测试。编辑 CountResourceTest 类以匹配

package org.acme.spring.scheduler;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;

import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class CountResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
                .when().get("/count")
                .then()
                .statusCode(200)
                .body(containsString("count"));  (1)
    }

}
1 确保响应包含 count

打包并运行应用程序

使用以下命令运行应用程序

命令行界面
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev

在另一个终端中,运行 curl localhost:8080/count 来检查计数器值。几秒钟后,重新运行 curl localhost:8080/count 以验证计数器是否已递增。

观察控制台以验证是否已显示以下消息:- Cron expression hardcoded - Cron expression configured in application.properties - Fixed Rate expression - Fixed Rate expression configured in application.properties 这些消息表明已触发了 @Scheduled 注解方法的执行。

与往常一样,可以使用以下命令打包应用程序

命令行界面
quarkus build
Maven
./mvnw install
Gradle
./gradlew build

并使用 java -jar target/quarkus-app/quarkus-run.jar 执行。

您还可以使用以下命令生成原生可执行文件

命令行界面
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true

使用属性表达式

Quarkus 支持在 application.properties 文件中使用属性表达式,因此为了外部化任务的配置,您应该将属性存储在 application.properties 文件中,并分别使用 fixedRateStringinitialDelayString 参数。

请注意,此配置是构建时配置,属性表达式将在构建时解析。

不支持的 Spring Scheduled 功能

Quarkus 目前仅支持 Spring @Scheduled 提供的一部分功能,更多功能正在规划中。目前,fixedDelayfixedDelayString 参数不受支持,换句话说,@Scheduled 方法总是独立执行。

重要的技术说明

请注意,Quarkus 中的 Spring 支持不会启动 Spring Application Context,也不会运行任何 Spring 基础架构类。Spring 类和注解仅用于读取元数据和/或用作用户代码方法的返回类型或参数类型。这对最终用户来说意味着,添加任意 Spring 库将不会有任何效果。此外,Spring 基础架构类(例如 org.springframework.beans.factory.config.BeanPostProcessor)将不会被执行。

相关内容