SpringBoot 集成 Quartz

本文深入探讨Quartz定时任务框架,介绍其核心概念、集群特性及SpringBoot集成方法。涵盖Job、Trigger、Scheduler等关键组件,解析cron表达式规则,提供实战配置示例。

Quartz

了解 Quartz
  • Quartz 是一个完全由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。
  • Quartz 可以与 J2EE 与 J2SE 应用程序相结合也可以单独使用。 Quartz 允许程序开发人员根据时间的间隔来调度作业。
  • Quartz 实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。
Quartz 核心概念
  • Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:void execute(JobExecutionContext context)
  • JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
  • Trigger 代表一个调度参数的配置,什么时候去调。
  • Scheduler 代表一个调度容器,一个调度容器中可以注册多个JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。
集群Quartz应用
  • 伸缩性
  • 高可用性
  • 负载均衡
  • Quartz可以借助关系数据库和JDBC作业存储支持集群。
  • Terracotta扩展quartz提供集群功能而不需要数据库支持

SpringBoot集成Quartz

1.添加依赖

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.1</version>
        </dependency>

2.创建任务类,添加注解@EnableScheduling(标注启动定时任务)

package com.bosssoft.bes.exam.task;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @ClassName: ScheduledTask
 * @Description: TODO
 * @Author: lujinshan
 * @Date: 2019/9/8 23:49
 * @Version: 1.0.0
 */

@Slf4j
@Configuration
@Component
@EnableScheduling
public class ScheduledTask {
    private final static Logger LOGGER = LoggerFactory.getLogger(ScheduledTask.class);

    public void markingDistribution() {
        LOGGER.info("开始定时任务的执行!");
        System.out.println("hello world!");
        LOGGER.info("定时任务执行结束!");
    }
}

3.Quartz配置类

package com.bosssoft.bes.exam.config;

import com.bosssoft.bes.exam.task.ScheduledTask;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

/**
 * @ClassName: QuartzConfig
 * @Description: TODO
 * @Author: lujinshan
 * @Date: 2019/9/8 23:45
 * @Version: 1.0.0
 */
@Slf4j
@Configuration
public class QuartzConfig {
    private final static Logger LOGGER = LoggerFactory.getLogger(QuartzConfig.class);

    @Bean(name = "jobDetail")
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduledTask task) {
        MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
        /*
         * 是否并发执行
         * 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
         * 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
         */
        jobDetail.setConcurrent(false);
        //设置定时任务的名字
        jobDetail.setName("exam-marking");
        //设置任务的分组,这些属性都可以在数据库中,在多任务的时候使用
        jobDetail.setGroup("exam");
        //为需要执行的实体类对应的对象
        jobDetail.setTargetObject(task);

        /*
         * markingDistribution为需要执行的方法
         * 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的markingDistribution方法
         */
        jobDetail.setTargetMethod("markingDistribution");
        LOGGER.info("jobDetail 初始化成功!");
        return jobDetail;
    }


    @Bean(name = "jobTrigger")
    public CronTriggerFactoryBean cronTriggerFactoryBean(MethodInvokingJobDetailFactoryBean jobDetail) {
        CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
        trigger.setJobDetail(jobDetail.getObject());
        //初始化的cron表达式(每天晚上03:00触发)
        trigger.setCronExpression("0 0 03 * * ?");
        //trigger的name
        trigger.setName("exam-marking");
        LOGGER.info("jobTrigger 初始化成功!");
        return trigger;
    }


    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactoryBean(Trigger trigger) {
        SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
        //用于quartz集群,QuartzScheduler启动时更新已存在的job
        factoryBean.setOverwriteExistingJobs(true);
        //延时启动,应用启动1秒后
        factoryBean.setStartupDelay(1);
        //注册触发器
        factoryBean.setTriggers(trigger);
        LOGGER.info("scheduler 初始化成功!");
        return factoryBean;
    }
}

MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。

注意:其setTargetObject所设置的是一个对象而不是一个类。

CronTriggerFactoryBean:定义一个触发器。

注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。

SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。

cronExpression表达式:

cronExpression表达式:

字段允许值允许的特殊字符
0-59, - * /
0-59, - * /
小时0-23, - * /
日期1-31, - * / L W C
月份1-12 或者 JAN-DEC, - * /
星期1-7 或者 SUN-SAT, - * / L C #
年(可选)留空, 1970-2099, - * /

“ * ”字符被用来指定所有的值。如:“ * ”在秒的字段域里表示“每秒”。

“-”字符被用来指定一个范围。如:“1-3”在小时域意味着“1点、2点、3点”。
“,”字符被用来指定另外的值。如:“MON,WED,FRI”在星期域里表示”星期一、星期三、星期五”。

“?”字符只在日期域和星期域中使用。它被用来指定“非明确的值”。当你需要通过在这两个域中的一个来指定一些东西的时候,它是有用的。看下面的例子你就会明白。

“L”字符指定在月或者星期中的某天(最后一天)。即“Last ”的缩写。但是在星期和月中“L”表示不同的意思,如:在月子段中“L”指月份的最后一天-1月31日,2月28日,如果在星期字段中则简单的表示为“7”或者“SAT”。如果在星期字段中在某个value值得后面,则表示“某月的最后一个星期value”,如“6L”表示某月的最后一个星期五。

“W”字符只能用在月份字段中,该字段指定了离指定日期最近的那个星期日。
“#”字符只能用在星期字段,该字段指定了第几个星期value在某月中。

表达式意义
“0 0 12 * * ?”每天中午12点触发
“0 10 09 ? * *”每天上午9:10触发
“0 10 09 * * ?”每天上午9:10触发
“0 10 09 * * ? *”每天上午9:10触发
“0 10 09 * * ? 2020”2020年的每天上午9:10分出发
“0 * 15 * * ?”在每天下午3点到下午3:59期间的每1分钟触发
“0 0/5 15 * * ?”在每天下午3点到下午3:55期间的每5分钟触发
“0 0/5 15,18 * * ?”在每天下午3点到3:55期间和下午6点到6:55期间的每5分钟触发
“0 0-5 15 * * ?”在每天下午3点到下午3:05期间的每1分钟触发
“0 10,44 15 ? 3 WED”每年三月的星期三的下午3:10和3:44触发
“0 10 09 ? * MON-FRI”周一至周五的上午09:10触发
“0 10 09 15 * ?”每月15日上午09:10触发
“0 10 09 L * ?”每月最后一日的上午09:10触发
“0 10 09 ? * 6L”每月的最后一个星期五上午09:10触发
“0 10 09 ? * 6L 2002-2005”2002年至2005年的每月的最后一个星期五上午09:10触发
“0 10 09 ? * 6#3”每月的第三个星期五上午09:10触发
### 集成 Quartz 实现定时任务调度 为了在 Spring Boot 项目中集成 Quartz 来实现定时任务调度,开发者可以通过引入相应的依赖来简化这一过程。每当向 Spring Boot 项目添加新的依赖项时,Spring Boot 自动配置会自动尝试根据该依赖项配置 bean[^4]。 #### 添加 Maven 或 Gradle 依赖 首先,在 `pom.xml` 文件中加入 Quartz 和其相关组件的支持: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> ``` 对于使用 Gradle 构建系统的项目,则应在 build.gradle 中添加如下内容: ```groovy implementation 'org.springframework.boot:spring-boot-starter-quartz' ``` #### 创建 Job 类 定义具体的作业类继承自 QuartzJobBean 并重写 executeInternal 方法完成业务逻辑处理工作: ```java import org.quartzDisallowConcurrentExecution; import org.quartz.PersistJobDataAfterExecution; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; @PersistJobDataAfterExecution @DisallowConcurrentExecution public class SampleJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("Executing job at " + new Date()); } } ``` 上述代码片段展示了创建一个简单的 Quartz 调度器实例的方法[^1]。 #### 定义 Scheduler Bean 通过 Java Config 方式注册 CronTriggerFactoryBean 及 MethodInvokingJobDetailFactoryBean 对象用于触发指定方法执行周期性的操作: ```java @Configuration @EnableScheduling public class QuartzConfig { @Autowired private ApplicationContext applicationContext; @Bean public JobDetail sampleJobDetail() { return JobBuilder.newJob(SampleJob.class).withIdentity("sampleJob").build(); } @Bean public Trigger sampleJobTrigger(@Qualifier("sampleJobDetail") JobDetail jobDetail) { return TriggerBuilder.newTrigger() .forJob(jobDetail) .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .build(); } } ``` 这段配置说明了如何设置每五秒运行一次的任务计划表[^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值