Spring Boot 集成Quartz的简单入门

一、Quartz的核心概念

Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:

1.持久性作业 - 就是保持调度定时的状态;
2.作业管理 - 对调度作业进行有效的管理;

Quartz是一个强大任务调度框架,可以用来干嘛?如一个OA系统需要在每周五9点自动生成数据报表,或者想每月10号自动还款,又或者每周给暗恋的女生定时发送邮件,又或者人事系统会在每天早晨8点给有待办的人员自动发送Email提醒。

下面介绍Quartz的三个核心概念(job,Trigger,Scheduler)。

1、任务job

job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。

Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。

Job:实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。

2、触发器Trigger

Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。

Trigger主要包含两种:SimpleTrigger和CronTriggerr。

3、调度器Scheduler

Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。

二、Quartz的几个常用API

Scheduler :用于与调度程序交互的主程序接口。

Job : 预先定义的希望在未来时间被调度程序执行的任务类,自定义。

JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。

JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。

Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。

JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如:任务名,组名等,这个声明的实例将作为一个实例执行的任务。

TriggerBuilder :触发器创建器,用于创建触发器trigger实例。

JobListener,TriggerListener,SchedulerListener监听器,用于对组件的监听。

三、Spring Boot 集成Quartz

1、创建项目并加入依赖(Spring Boot的扩展默认集成Quartz)

<!-- quartz定时任务 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>

2、新建Job任务

/**
 * 新建 Quartz的Job 任务
 */
public class MyJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Hello Quartz");
    }
}

3、创建Schedule,执行任务

public class QuartzTest {

    public static void main(String[] args) throws Exception {
        // 1. 创建一个JobDetail,把实现了Job接口的类邦定到JobDetail 构建者模式 绑定job withIdentity这里起一个唯一的名字
        JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
                .withIdentity("job1") // 唯一标识
                .build();
        // 2.创建一个Trigger触发器的实例,定义该job立即执行,并且每2秒执行一次,一直执行 repeatForever重复
        SimpleTrigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("trigger1") // 唯一标识
                .startNow() // 立即生效
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withIntervalInSeconds(2) // 每2秒执行一次
                        .repeatForever()) // 一直重复执行
                .build();
        // 3.创建schedule调度器并执行   StdSchedulerFactory 工厂模式
        StdSchedulerFactory factory = new StdSchedulerFactory();
        // 获取调度器实例
        Scheduler scheduler = factory.getScheduler();
        // 开启调度器
        scheduler.start();
        // 把SimpleTrigger和JobDetail注册给调度器
        scheduler.scheduleJob(jobDetail, trigger);
        // 关闭调度器
        // scheduler.shutdown();
    }

}

运行程序,控制台会每两秒打印一个"Hello Quartz"。

三、Quartz核心详解(部分)

1、Job和JobDetail

Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。

JobDetail用来绑定Job,为Job实例提供许多属性:

name group jobClass jobDataMap

JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。

为什么设计成JobDetail + Job,不直接使用Job

JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。 这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。

2、Trigger、SimpleTrigger、CronTrigger

Trigger

Trigger是Quartz的触发器,会去通知Scheduler何时去执行对应Job。

new Trigger().startAt():表示触发器首次被触发的时间;

new Trigger().endAt():表示触发器结束触发的时间;

SimpleTrigger

SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。

下面的程序就实现了程序运行5s后开始执行Job,执行Job 5s后结束执行:

Date startDate = new Date();
startDate.setTime(startDate.getTime() + 5000);

Date endDate = new Date();
endDate.setTime(startDate.getTime() + 5000);

Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
        .usingJobData("trigger1", "这是jobDetail1的trigger")
        .startNow()//立即生效
        .startAt(startDate)
        .endAt(endDate)
        .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInSeconds(1)//每隔1s执行一次
        .repeatForever())
        .build();//一直执行

CronTrigger

CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的。

public class MyScheduler2 {
    public static void main(String[] args) throws SchedulerException, InterruptedException {
        //1.创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
        JobDetail jobDetail=JobBuilder.newJob(PrintWordsJob.class)
                .usingJobData("jobDetail", "这个Job用来测试的")
                .withIdentity("job","group")
                .build();
        //2.触发器
        CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行
                .usingJobData("trigger1", "这是jobDetail1的trigger")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))//表示每次0秒时候执行。
                .build();
        //3.调度器
        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        scheduler.scheduleJob(jobDetail,trigger);
        System.out.println("--------scheduler start ! ------------");
        scheduler.start();
        System.out.println("--------scheduler shutdown ! ------------");

    }
}

3、JobDetail & Job和JobDataMap

JobDetail是任务的定义,而Job是任务的执行逻辑。在JobDetail里会引用一个Job Class定义。

每一个JobDetail都会有一个JobDataMap。JobDataMap本质就是一个Map的扩展类,只是提供了一些更便捷的方法,比如getString()之类的。

1.编写触发类

public static void demo2()throws Exception{
    //1. 创建一个JobDetail,把实现了Job接口的类邦定到JobDetail
    JobDetail jobDetail= JobBuilder.newJob(SecondJob.class)
        	.withIdentity("demo2")
            .usingJobData("name","zhangan")
            .usingJobData("age",22)
            .build();
    CronTrigger trigger=TriggerBuilder.newTrigger()
        .withIdentity("trriger2")
        .withSchedule(CronScheduleBuilder
        .cronSchedule("45 50 10 * * ?"))
        .build();
    //创建schedule实例
    StdSchedulerFactory factory = new StdSchedulerFactory();
    //获取调度器实例
    Scheduler scheduler = factory.getScheduler();
    //开启调度器
    scheduler.start();
    //把SimpleTrigger和JobDetail注册给调度器
    scheduler.scheduleJob(jobDetail,trigger);

}

2.编写具体任务类

public class SecondJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //打印当前的执行时间 例如 2021-08-30 10:12:00
        Date date = new Date();
        //格式化时间
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("现在的时间是:"+ sf.format(date));
        //具体的业务逻辑
        System.out.println("开始生成任务报表 或 开始发送邮件");
        JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
        String name= jobDataMap.getString("name");
        int age= jobDataMap.getInt("age");
        System.out.println("name="+name+",age="+age);

    }
}
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值