SpringBoot系列记录(九)————Springboot整合Quartz

1、Quartz核心概念

首先我们需要明白 Quartz 的几个核心概念,这样理解起 Quartz 的原理就会变得简单了。

  1. Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,如下:void execute(JobExecutionContext context) 
  2. JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
  3. Trigger 代表一个调度参数的配置,什么时候去调。
  4. Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了

2、具体分析

2.1 Job其实由三部分组成:

  •       JobDetail: 用于描述这个Job是做什么的
  •       一个实现Job接口的类:告诉Quartz具体干什么活的
  •      JobDataMap: 给 Job 提供参数用的
JobDetail jobDetail = newJob(TestJob.class)
                .withIdentity("job1","group2")
                .usingJobData("test","sparrow")
                .build();

可以看到我们在创建JobDetail的时候,将要执行的job的类名传给了JobDetail,所以scheduler就知道了要执行何种类型的job。每次当scheduler执行job时,在调用其execute(…)方法之前会创建该类的一个新的实例;执行完毕,对该实例的引用就被丢弃了,实例会被垃圾回收;

这种执行策略带来的一个后果是,job必须有一个无参的构造函数(当使用默认的JobFactory时);另一个后果是,在job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留,那这个时候JobDataMap就可以干活了,JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据。

JobDataMap 除了像上面使用usingJobData 方式之外,还可以

 jobDetail.getJobDataMap().put("test","testOne");

2.2 常用的两种Trigger

Trigger 就是触发器的意思,用来指定什么时间开始触发,触发多少次,每隔多久触发一次。最常用SimpleTriggerCronTrigger这两种。

2.2.1、SimpleTrigger

Trigger trigger = newTrigger().withIdentity("myTrigger","group1")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(5)
                        .withRepeatCount(10))
                .build();

SimpleTrigger的属性包括:开始时间、结束时间、重复次数以及重复的间隔;上面这段代码的意思就是从现在开始,每隔5s执行一次,一共执行10次。

重复次数,可以是0、正整数,以及常量SimpleTrigger.REPEAT_INDEFINITELY。重复的间隔,必须是0,或者long型的正数,表示毫秒。注意,如果重复间隔为0,trigger将会以重复次数并发执行(或者以scheduler可以处理的近似并发数)。

定义开始时间,比如下方代码:5s后开始     对应的结束使用endAt

 Date startTime = DateBuilder.futureDate(5, DateBuilder.IntervalUnit.SECOND);
        Trigger trigger1 = newTrigger().withIdentity("myTrigger","group1")
                .startAt(startTime)
                .build();

2.2.2、CronTrigger

使用CronTrigger最主要的就是Cron表达式,关于表达式后面会专门写一篇博文,这里直接放个例子了,每天上午10点42触发

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(dailyAtHourAndMinute(10, 42))
    .forJob("myJob", "group1")
    .build();

或者

trigger = newTrigger()
    .withIdentity("trigger3", "group1")
    .withSchedule(cronSchedule("0 42 10 * * ?"))
    .forJob("myJob", "group1")
    .build();

3、Springboot整合Quartz

以上只是简单地介绍了Quartz,好在整合过程中有个过度,更多内容可以查看Quartz相关资料

pom.xml

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

 业务代码

public class TestJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        JobDetail jobDetail = jobExecutionContext.getJobDetail();
        String test = jobDetail.getJobDataMap().getString("test");
        System.out.println(test+new Date());
    }
}

测试类:

 @Test
    public void testThree() throws Exception{
        //创建调度器
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //定义一个触发器
        Trigger trigger = newTrigger().withIdentity("myTrigger","group1")
                .startNow()
                .withSchedule(simpleSchedule()
                        .withIntervalInSeconds(5)
                        .withRepeatCount(5))
                .build();
        //定义一个JobDetail
        JobDetail jobDetail = newJob(TestJob.class)
                .withIdentity("job1","group2")
                .usingJobData("test","sparrow")
                .build();
        //调度加入这个job
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
        //等待任务执行完再关闭
        Thread.sleep(20000);
        scheduler.shutdown(true);
    }

执行结果:

 扩展:实际应用

以上只是测试了一下是否可用,下面来个实际应用的例子:

先创建一个任务类,具体的业务逻辑根据实际情况来,我这里是系统给我发送一个邮件

public class DailyMailJob implements Job {

    Logger logger = LoggerFactory.getLogger(DailyMailJob.class);

    @Autowired
    IMailService mailService;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String content = "花有重开之日,人无再少年,走好脚下的路,笔直看眼前";
        mailService.sendSimpleMail("[email protected]", Constant.DAILY_SUBJECT,content);
        logger.info("----------------邮件已发送----------------");
    }
}

再写个任务调度配置类    这里只是简单举个例子

@Configuration
public class SchedulerConfig {

    @Autowired
    Scheduler scheduler;

    @Bean
    public void startJob() throws SchedulerException {
        customJobOne(scheduler);
        //启动
        scheduler.start();
    }

   private void customJobOne(Scheduler scheduler) throws SchedulerException {
       //创建调度器
       //Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
       //定义一个触发器
       Trigger trigger = newTrigger().withIdentity("mailTriggerOne","mailGroup")
               .startNow()
               .withSchedule(cronSchedule("0 36 16 * * ?"))
               .build();
       //定义一个JobDetail
       JobDetail jobDetail = newJob(DailyMailJob.class)
               .withIdentity("mailJobOne","JobGroup")
               .build();
       //调度加入这个job
       scheduler.scheduleJob(jobDetail,trigger);
   }
}

 结果:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章