Spring Boot 如何实现定时任务
Spring Boot 如何实现定时任务
在现代的微服务架构中,定时任务是一个常见的需求。无论是数据定时同步、定时清理缓存,还是定时发送通知,Spring Boot 提供了非常强大且灵活的定时任务支持。本文将详细介绍如何在 Spring Boot 中实现定时任务,包括使用 @Scheduled
注解和集成 Quartz 调度框架的两种方式。
一、使用 @Scheduled
注解实现定时任务
Spring Boot 提供了内置的 @Scheduled
注解,可以非常方便地实现简单的定时任务。这种方式适合轻量级的定时任务,且不需要复杂的调度逻辑。
1.1 添加依赖
在 Spring Boot 项目中,@Scheduled
注解是内置支持的,因此不需要额外添加依赖。
1.2 启用定时任务支持
在主类或配置类上添加 @EnableScheduling
注解,启用定时任务支持。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;@SpringBootApplication
@EnableScheduling
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
}
1.3 定义定时任务
在任意的 @Component
或 @Service
类中,使用 @Scheduled
注解定义定时任务。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class MyScheduledTasks {// 每两小时运行一次@Scheduled(cron = "0 0 0/2 * * ?")public void runTask() {System.out.println("任务执行了!当前时间:" + new java.util.Date());}
}
1.4 常见的 Cron 表达式
0 0/30 * * * ?
:每30分钟执行一次。0 0 9-17 * * ?
:每天的9点到17点之间,每小时执行一次。0 0 8,14 * * ?
:每天的8点和14点各执行一次。0 0-5 14 * * ?
:在每天14点的第0分钟至第5分钟的每分钟执行一次。0 0-5 14,18 * * ?
:在每天14点和18点的第0分钟至第5分钟的每分钟执行一次。
1.5 注意事项
-
线程池配置:默认情况下,Spring 的
@Scheduled
使用单线程执行任务。如果任务较多或任务执行时间较长,可能会导致任务延迟。可以通过配置ThreadPoolTaskExecutor
来指定线程池大小:import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.config.ScheduledTaskRegistrar;@Configuration public class SchedulingConfig implements SchedulingConfigurer {@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); // 设置线程池大小executor.setThreadNamePrefix("scheduled-task-");executor.initialize();taskRegistrar.setTaskExecutor(executor);} }
-
任务执行时间:
@Scheduled
的任务执行时间是基于服务器的系统时间,因此需要确保服务器时间准确。
二、使用 Quartz 调度框架实现定时任务
对于更复杂的调度需求,如任务持久化、任务恢复、任务分组等,Quartz 是一个强大的调度框架。Spring Boot 提供了对 Quartz 的集成支持。
2.1 添加依赖
在 pom.xml
文件中添加 Quartz 和 Spring Boot 的集成依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2.2 配置 Quartz
在 application.properties
文件中配置 Quartz 的相关参数:
# 配置Quartz的调度器名称
spring.quartz.scheduler.name=myScheduler
# 配置线程池大小
spring.quartz.scheduler.thread-count=10
# 配置任务存储类型为内存
spring.quartz.job-store.type=memory
# 配置任务存储的数据库连接(如果使用数据库存储任务)
# spring.quartz.job-store.driver-class-name=com.mysql.cj.jdbc.Driver
# spring.quartz.job-store.url=jdbc:mysql://localhost:3306/quartz_db
# spring.quartz.job-store.user=root
# spring.quartz.job-store.password=root
2.3 定义任务类
创建一个实现 Job
接口的任务类:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;public class MyJob implements Job {@Overridepublic void execute(JobExecutionContext context) throws JobExecutionException {System.out.println("任务执行了!当前时间:" + new java.util.Date());}
}
2.4 配置任务和触发器
在配置类中定义任务和触发器:
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class QuartzConfig {@Beanpublic JobDetail myJobDetail() {return JobBuilder.newJob(MyJob.class).withIdentity("myJob", "group1").build();}@Beanpublic Trigger myJobTrigger() {return TriggerBuilder.newTrigger().withIdentity("myTrigger", "group1").startNow().withSchedule(CronScheduleBuilder.cronSchedule("0 0 0/2 * * ?")).forJob(myJobDetail()).build();}
}
2.5 注意事项
- 任务持久化:Quartz 支持将任务存储在数据库中,即使应用重启,任务也可以继续执行。需要配置数据库连接信息。
- 任务分组:可以通过
withIdentity
方法为任务和触发器指定分组,方便管理。 - 任务恢复:Quartz 支持任务恢复,即使任务在执行过程中应用崩溃,任务也可以在应用重启后继续执行。
三、总结
Spring Boot 提供了两种实现定时任务的方式:@Scheduled
注解和 Quartz 调度框架。@Scheduled
适合简单的定时任务,而 Quartz 提供了更强大的功能,适合复杂的调度需求。根据实际需求选择合适的方式即可。
- 如果任务简单且不需要复杂的调度逻辑,推荐使用
@Scheduled
。 - 如果需要任务持久化、任务恢复或复杂的调度策略,推荐使用 Quartz。
相关文章:
Spring Boot 如何实现定时任务
Spring Boot 如何实现定时任务 在现代的微服务架构中,定时任务是一个常见的需求。无论是数据定时同步、定时清理缓存,还是定时发送通知,Spring Boot 提供了非常强大且灵活的定时任务支持。本文将详细介绍如何在 Spring Boot 中实现定时任务&…...
免费开源 PDF 阅读器 自带虚拟打印机功能 多格式兼容
各位办公小能手们,今天咱来聊聊一款超厉害的PDF工具——PDFLite! 这PDFLite啊,那可是轻量级、免费又开源的好东西。它能干啥呢?主要就是能读PDF文件,还能转换文件格式,做基础的文档管理。下面咱就说说它的…...

换宽带ip地址会变吗?同一个宽带如何切换ip地址
在当今互联网时代,IP地址作为网络设备的"身份证",其重要性不言而喻。许多用户在使用宽带时都会遇到这样的疑问:换宽带IP地址会变吗?同一个宽带如何切换IP地址?本文将深入探讨这一问题,帮助读者全…...

第100+41步 ChatGPT学习:R语言实现误判病例分析
本期是《第33步 机器学习分类实战:误判病例分析》的R版本。 尝试使用Deepseek-R1来试试写代码,效果还不错。 下面上R语言代码,以Xgboost为例: # 加载必要的库 library(caret) library(pROC) library(ggplot2) library(xgboost)…...

贝锐蒲公英工业路由器R300A海外版:支持多国4G频段,全球组网
为更好地满足全球部署和企业出海项目的多样化需求,贝锐蒲公英异地组网工业路由器R300A海外版全新上市,并已正式上架速卖通!无论是跨国分支机构协同办公,还是海外工厂设备远程运维,R300A海外版都能为企业提供灵活、高性…...
字符串索引、幻读的解决方法
1. 给字符串加索引 1.1. 前缀索引vs完整索引 假设有一个支持邮箱登录的系统,用户表定义如下: CREATE TABLE SUser(ID BIGINT UNSIGNED PRIMARY KEY,email VARCHAR(64),... ) ENGINEInnoDB; 为了根据邮箱查询用户信息,常用的查询语句如下&…...

[特殊字符] 超强 Web React版 PDF 阅读器!支持分页、缩放、旋转、全屏、懒加载、缩略图!
在现代 Web 项目中,PDF 浏览是一个常见需求:从政务公文到合同协议,PDF 文件无处不在。但很多方案要么体验不佳,要么集成复杂。今天,我给大家带来一个开箱即用、功能全面的 PDF 预览组件 —— [PDFView](https://www.np…...

wireshark分析国标rtp ps流
1.将抓到的tcp或者udp视频流使用decode as 转为rtp包 2.电话->RTP->RTP播放器 选择Export 里面的Payload 就可以导出原始PS流...
jetpack compose 界面刷新的几种方式 如何避免无效的界面刷新
界面刷新的几种方式 在 Jetpack Compose 中,界面刷新主要依赖于数据的响应式变化。以下是几种常见的界面刷新方式及其原理: 1. 使用 MutableState(基础方式) 通过 mutableStateOf 创建可观察的状态,状态变化时会触发…...

【STM32+LAN9252+HAL库】EtherCAT从站搭建 保姆级教程
目录 一、生成协议栈及XML文件 二、使用stm32CuboMX配置外设 三、协议栈移植 鉴于本人对EtherCAT的掌握程度十分有限,这篇文章仅作为我搭建基础从站的过程记录不做更多讲解。本文内容主要为SPI模式的基础搭建,更多深入的学习资料和细节,大家…...

【harbor】--基础使用
推送 不同的管理工具都有说明 以docker为例 # 第一步--打标签 docker tag SOURCE_IMAGE[:TAG] 192.168.121.201:801/haohao_fist/REPOSITORY[:TAG] # 第二步--推送 docker push 192.168.121.201:801/haohao_fist/REPOSITORY[:TAG]默认push推送为https push会失败 解决办法…...

JAVA学习 DAY1 初识JAVA
本系列可作为JAVA学习系列的笔记,文中提到的一些练习的代码,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。 点赞关注不迷路!您的点赞、关注和收藏是对小编最大的支持和鼓励! 系列文章目录…...
*JavaScript中的Symbol类型:唯一标识符的艺术
JavaScript中的Symbol类型:唯一标识符的艺术 在JavaScript的世界中,数据类型一直是开发者关注的焦点。从基本的Number、String到后来的Symbol,每一种类型的引入都为语言本身注入了新的活力。而今天我们要聊的主角——Symbol,是ES…...

Vue能启动但访问空白?并报”export ‘default’ (imported as ‘Vue’) was not found in ‘vue’
场景 如图,vue项目的node_modules下载顺利,启动也顺利,但是访问却为空白页面 虽然页面是空白,但是通过浏览器控制台可以看出并非简单的空白,确实有不兼容问题在里面 分析问题 从上图浏览器控制台可以看出,…...

Electron-vite【实战】MD 编辑器 -- 系统菜单(含菜单封装,新建文件,打开文件,打开文件夹,保存文件,退出系统)
最终效果 整体架构 src/main/index.ts import { createMenu } from ./menu在 const mainWindow 后 // 加载菜单createMenu(mainWindow)src/main/menu.ts import { BrowserWindow, Menu, MenuItem, MenuItemConstructorOptions, dialog, shell } from electron import fs from…...
如何将 PDF 文件中的文本提取为 YAML(教程)
这篇博客文章将向你展示如何将 PDF 转换为 YAML,通过提取带有结构标签的标记内容来实现。 什么是结构化 PDF? 一些 PDF 文件包含结构化内容,也称为带标签(tagged)或标记内容(marked content)&…...

【Docker系列】Docker 容器内安装`ps`命令
博客目录 一、为什么需要在 Docker 容器中安装ps命令二、不同 Linux 发行版的安装方法1. Alpine Linux 镜像的安装方法2. Debian/Ubuntu 镜像的安装方法3. CentOS/RHEL 镜像的安装方法 三、验证安装与基本使用四、永久解决方案:修改 Dockerfile1. Alpine 基础镜像的…...
Netty 实战篇:为 Netty RPC 框架增加超时控制与重试机制,防止系统雪崩
本文介绍如何在自研 Netty RPC 框架中实现超时控制与重试机制。合理的超时策略可以避免调用卡死,重试机制可以提升调用成功率,在高可用系统中不可或缺。 一、为什么要有超时和重试? RPC 是跨进程调用,失败是常态。常见问题包括&a…...
PDFGear——完全免费且功能强大的PDF处理软件
关键词 :PDFGear、免费、跨平台、多功能、OCR 概要 :PDFGear是一款完全免费且功能强大的PDF处理软件,支持Windows、macOS、iOS和Android等多平台使用。它集PDF阅读、编辑、格式转换、OCR识别及AI智能助手于一体,满足用户多样化文档…...

华为OD机试真题——生成哈夫曼树(2025A卷:100分)Java/python/JavaScript/C/C++/GO六种最佳实现
2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《生成…...

大厂前端研发岗位设计的30道Webpack面试题及解析
文章目录 一、基础核心二、配置进阶三、性能优化四、Loader原理五、Plugin机制六、高级应用七、工程化实战八、原理深挖九、异常处理十、综合场景一、基础核心 Webpack的核心概念是什么? 解析:入口(entry)、输出(output)、加载器(loader)、插件(plugins)、模式(mode)。Loader…...

Oracle中EXISTS NOT EXISTS的使用
目录 1.IN与EXISTS EXISTS用法总结 2.NOT IN与NOT EXISTS 3.not in 中 null的用法 4.EXISTS和IN的区别 (面试常问) 1.IN与EXISTS 示例:在 DEPT 表中找出在 EMP 表中存在的部门编号; 方法一:使用in select DEPTNO from DEPT where D…...

01.认识Kubernetes
什么是Kubernets 套用官方文档对Kubernetes的定义,翻译成中文的意思是: Kubernetes,也称为k8,是一个用于自动化部署、扩展和管理容器化应用程序的开源系统。 它将组成应用程序的容器分组为逻辑单元,以便于管理和发现…...
基于AI生成测试用例的处理过程
基于AI生成测试用例的处理过程是一个结合机器学习、自然语言处理(NLP)和领域知识的系统性流程。以下是其核心步骤和关键技术细节,以帮助理解如何利用AI自动化生成高效、覆盖全面的测试用例。 1. 输入分析与需求建模 目标 将用户需求、系统文…...

【PostgreSQL 02】PostgreSQL数据类型革命:JSON、数组与地理信息让你的应用飞起来
PostgreSQL数据类型革命:JSON、数组与地理信息让你的应用飞起来 关键词 PostgreSQL高级数据类型, JSONB, 数组类型, PostGIS, 地理信息系统, NoSQL, 文档数据库, 空间数据, 数据库设计, PostgreSQL扩展 摘要 PostgreSQL的高级数据类型是其区别于传统关系数据库的核心…...

Acrobat DC v25.001 最新专业版已破,像word一样编辑PDF!
在数字化时代,PDF文件以其稳定性和通用性成为了文档交流和存储的热门选择。无论是阅读、编辑、转换还是转曲,大家对PDF文件的操作需求日益增加。因此,一款出色的PDF处理软件不仅要满足多样化的需求,还要通过简洁的界面和强大的功能…...
tmux基本原理
目录 **一、核心架构:客户端-服务器模型****二、终端虚拟化:伪终端(PTY)****三、会话持久化原理****四、窗格分割的实现****五、关键系统调用****六、与传统终端对比****七、典型工作流示例****总结** tmux(Terminal M…...
RAGFlow从理论到实战的检索增强生成指南
目录 前言 一、RAGFlow是什么?为何需要它? 二、RAGFlow技术架构拆解 三、实战指南:从0到1搭建RAGFlow系统 步骤1:环境准备 步骤2:数据接入 步骤3:检索与生成 四、优化技巧:让RAGFlow更精…...
【Java】ForkJoin 框架
在Java中,ForkJoin框架是并行编程的一个重要工具,它主要用于处理可以分解为多个子任务的复杂任务。ForkJoin框架的核心是ForkJoinPool,它是一个线程池,专门用于执行ForkJoinTask任务。通过将大任务分解为多个小任务,并…...
PHP实战:安全实现文件上传功能教程
HTML部分: <form action"upload.php" method"post" enctype"multipart/form-data"> <input type"file" name"userfile"> <input type"submit" value"上传"> <…...