栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

在Spring Boot 中使用定时框架Quartz,触发时间在数据库表中获取

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Spring Boot 中使用定时框架Quartz,触发时间在数据库表中获取

背景:在前端页面新建定时任务,将任务存入数据库,包含触发时间及触发模式

数据库表触发时间字段如下:

 

一、Quartz的介绍

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,是完全由java开发的一个开源的任务日程管理系统,“任务进度管理器”就是一个在预先确定(被纳入日程)的时间到达时,负责执行(或者通知)其他软件组件的系统。

Quartz用一个小Java库发布文件(.jar文件),这个库文件包含了所有Quartz核心功能。这些功能的主要接口(API)是Scheduler接口。它提供了简单的操作,例如:将任务纳入日程或者从日程中取消,开始/停止/暂停日程进度。

不了解Quartz的可以查看下面的相关文章:

https://www.cnblogs.com/wangjiming/p/10027439.html

二、将Quartz引入Spring Boot以及使用

1、导入依赖的jar包:


    org.springframework.boot
    spring-boot-starter-quartz

版本直接由spring boot控制

2、新建一个任务类,并实现Job接口,此接口只有一个方法void execute(JobExecutionContext jobExecutionContext)

public class MyJob implements Job {

   private static IDutyService dutyService;
   static {
      dutyService = SpringUtil.getBean(IDutyService.class);
   }

   @Override
   public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
      DutyDefEntity dutyDef = (DutyDefEntity) jobExecutionContext.getJobDetail().getJobDataMap().get("dutyDef");// 获取定义任务数据
      Boolean success = this.dutyService.saveDuty(dutyDef);// 实现发布任务的业务接口
      if (success) {
         System.out.println("发布例行任务成功");
      }
   }
}

3、接下来新建一个工厂类,创建定时任务

@Service
@Component
public class MySchedulerFactory {

   @Autowired
   SchedulerFactoryBean schedulerFactoryBean;

   // 获取scheduler
   private Scheduler getScheduler(){
      return schedulerFactoryBean.getScheduler();
   }
   // 项目启动 开启任务
   public void startJob(DutyDefEntity dutyDefEntity) throws SchedulerException, ClassNotFoundException {
      Scheduler scheduler = getScheduler(); // 获取scheduler
      JobKey jobKey = JobKey.jobKey(Func.toStr(dutyDefEntity.getId()), "group1");//根据唯一标识符获取任务
      Class clazz = (Class) Class.forName("org.springblade.modules.time.MyJob");
      JobDetail jobDetail1 = scheduler.getJobDetail(jobKey);
      String cron = "";
      // 发布模式:隔天interval,指定日期specify
      if (dutyDefEntity.getAutoMode().equals("interval")) {// 隔天interval
         String[] time = dutyDefEntity.getAutoTime().toString().split(":");// 时分秒(数据库存的是时分秒)
         // 如:每隔2天,在12点34分发布
         // cron = "0 34 12 */2"
         cron = "0 " + time[1] + " " + time[0] + " */" + dutyDefEntity.getAutoInterval();
      }
      if (dutyDefEntity.getAutoMode().equals("specify")) {// 指定日期specify
         String[] time = dutyDefEntity.getAutoTime().toString().split(":");// 时分秒
         // dutyDefEntity.getAutoMouth() 多个月份必须以英文逗号隔开
          // 如:在4月和6月的23号,12点34分发布
         // cron = "0 34 12 23 4,6 ? *"
         cron = "0 " + time[1] + " " + time[0] + " " + dutyDefEntity.getAutoDay() + " " + dutyDefEntity.getAutoMouth() + " ? *";
      }
      if (jobDetail1==null){// 不存在就新建定时任务
         JobDetail jobDetail = JobBuilder.newJob(clazz)
            .withIdentity(Func.toStr(dutyDefEntity.getId()), "group1").build();
         jobDetail.getJobDataMap().put("dutyDef", dutyDefEntity);// 将要发布的任务传递到任务的实现类MyJob中
         CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
         CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(Func.toStr(dutyDefEntity.getId()), "group1")
            .withSchedule(scheduleBuilder).build();
         scheduler.scheduleJob(jobDetail, cronTrigger);
      }else {// 存在就修改触发时间
         TriggerKey triggerKey = new TriggerKey(Func.toStr(dutyDefEntity.getId()), "group1");
         CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
         String oldTime = cronTrigger.getCronExpression();
         if (!oldTime.equalsIgnoreCase(cron)) {
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron);
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(Func.toStr(dutyDefEntity.getId()), "group1")
               .withSchedule(cronScheduleBuilder).build();
            scheduler.rescheduleJob(triggerKey, trigger);
         }
      }
   }
}

JobDetail是任务的定义,而Job是任务的执行逻辑。在JobDetail里会引用一个Job Class定义。每一个JobDetail都会有一个JobDataMap。JobDataMap本质就是一个Map的扩展类,只是提供了一些更便捷的方法,比如getString()之类的。

4、新建监听器类

@Configuration
public class StartSchedulerListener implements ApplicationListener {

   @Autowired
   public MySchedulerFactory mySchedulerFactory;

   // springboot 启动监听
   @Override
   public void onApplicationEvent(ContextRefreshedEvent event) {

   }

   //注入SchedulerFactoryBean
   @Bean
   public SchedulerFactoryBean schedulerFactoryBean() {
      SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
      return schedulerFactoryBean;
   }
}

其实可以不用建立这个类,可以将SchedulerFactoryBean直接在MySchedulerFactory 中注入bean,代码如下:

@Resource
privite SchedulerFactoryBean schedulerFactoryBean;

OK,现在需要去调用startJob方法,执行定时任务

5、利用springboot自带的定时器,每隔10分钟从数据库中获取最新的数据,并启动定时任务

@Component
@EnableScheduling
public class StartJob {
   @Resource
   private IDutyDefService dutyDefService;

   @Autowired
   public MySchedulerFactory mySchedulerFactory;

   
   @Scheduled(initialDelay=1000, fixedDelay=600000) // 第一次延迟1秒执行,然后在上一次执行完毕时间点10分钟秒再次执行;
   public void startTaskTimerByTenMin() {
      try {
         // 获取例行任务定义
         QueryWrapper wrapper = new QueryWrapper<>();
         List list = dutyDefService.list(wrapper);
         if (Func.isNotEmpty(list)) {
            for (DutyDefEntity dutyDefEntity : list) {
               mySchedulerFactory.startJob(dutyDefEntity);// 开启定时任务,将要发布的任务传递进去
            }
         }
      } catch (Exception e) {

      }
   }
}

完成!!!!!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820088.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号