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 应用程序中的调度。