Spring Boot 调度任务
最后修改于 2023 年 7 月 16 日
Spring Boot 调度任务教程展示了如何在 Spring Boot 应用程序中使用 @Scheduled 调度任务。
Spring Boot 是一个流行的框架,用于构建 Java、Kotlin 或 Groovy 中的企业应用程序。
Spring Boot 调度任务
@EnableScheduling 在 Spring Boot 应用程序中启用调度。使用 @Scheduled 注解修饰的方法会定期运行。这些方法应该返回 void 并且不应该有任何参数。
ScheduledAnnotationBeanPostProcessor 是一个 bean 后处理器,它注册用 @Scheduled 注解的方法,这些方法将由 TaskScheduler 根据通过注解提供的 fixedRate、fixedDelay、cron 表达式调用。 fixedDelay 属性以连续执行任务之间 n 毫秒的固定延迟运行任务。 fixedRate 以每 n 毫秒运行一次调度任务。它不会检查任务的任何先前执行。
@Scheduled(cron="pattern") 允许定义 crontab 模式来运行任务。该模式是一个由六个单独的空格分隔的字段组成的列表:分别代表秒、分钟、小时、日、月、星期。月份和星期几的名称可以用英文名称的前三个字母表示。例如,"0 0/30 8-10 * * *" cron 模式将任务安排在每天 8:00、8:30、9:00、9:30、10:00 和 10:30 运行。
Spring Boot 调度示例
在以下应用程序中,我们以 15 秒的固定频率调度一个任务。该任务连接到一个网站并读取其 date 标头。
build.gradle
...
src
├───main
│ ├───java
│ │ └───com
│ │ └───zetcode
│ │ │ Application.java
│ │ ├───scheduling
│ │ │ ScheduledTasks.java
│ │ └───service
│ │ HeadRequestService.java
│ └───resources
│ application.properties
└───test
└───java
这是 Spring Boot 应用程序的项目结构。
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.1'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.zetcode'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
这是 Gradle 构建文件。我们添加了 spring-boot-starter-web 用于一个简单的 web 应用程序。
spring.main.banner-mode=off spring.main.log-startup-info=false
application.properties 文件包含应用程序配置设置。使用 spring.main.banner-mode,我们关闭了 Spring Boot banner,使用 spring.main.log-startup-info 属性,我们关闭了启动日志信息。
package com.zetcode.scheduling;
import com.zetcode.service.HeadRequestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTasks {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private final HeadRequestService headRequestService;
@Autowired
public ScheduledTasks(HeadRequestService headRequestService) {
this.headRequestService = headRequestService;
}
@Scheduled(fixedRate = 15000)
public void getHeadValue() {
log.info("Value: {}", headRequestService.doHeadRequest());
}
}
在 ScheduledTasks 中,我们调度一个任务每 15 秒运行一次。
@Scheduled(fixedRate = 15000)
public void getHeadValue() {
log.info("Value: {}", headRequestService.doHeadRequest());
}
每 15 秒,HeadRequestService 的 doHeadRequest 方法被调用。
package com.zetcode.service;
import com.zetcode.scheduling.ScheduledTasks;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
@Service
public class HeadRequestService {
private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);
private HttpHeaders headers;
public String doHeadRequest() {
HttpClient client = HttpClient.newHttpClient();
try {
var request = HttpRequest.newBuilder(URI.create("http://webcode.me"))
.method("HEAD", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<Void> response = client.send(request,
HttpResponse.BodyHandlers.discarding());
headers = response.headers();
} catch (IOException | InterruptedException e) {
log.error("Failed to send HEAD request");
}
var opt = headers.firstValue("date");
return opt.orElse("");
}
}
doHeadRequest 方法向 webcode.me 网站发出 HEAD 请求,并从其响应中检索 date 标头。
package com.zetcode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableScheduling
@RestController
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@GetMapping(value = "/", produces = MediaType.TEXT_PLAIN_VALUE)
private String home() {
return "home page";
}
}
在 Applicaiton 中,我们设置了 Spring Boot 应用程序。使用 @EnableScheduling,我们为应用程序启用调度。此外,我们添加了一个简单的网页,返回文本。
$ ./gradlew bootRun ... 2023-07-17T18:38:54.662+02:00 INFO 16732 --- [ scheduling-1] com.zetcode.scheduling.ScheduledTasks : Value: Mon, 17 Jul 2023 16:37:43 GMT 2023-07-17T18:39:09.167+02:00 INFO 16732 --- [ scheduling-1] com.zetcode.scheduling.ScheduledTasks : Value: Mon, 17 Jul 2023 16:37:58 GMT 2023-07-17T18:39:24.165+02:00 INFO 16732 --- [ scheduling-1] com.zetcode.scheduling.ScheduledTasks : Value: Mon, 17 Jul 2023 16:38:13 GMT
我们使用 ./gradlew bootRun 运行应用程序。在输出中,我们可以看到已调度方法的消息。
在本文中,我们研究了 Spring Boot 应用程序中的调度。