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

在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@Componentpublic 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、新建监听器类

@Configurationpublic 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,代码如下:

@Resourceprivite SchedulerFactoryBean schedulerFactoryBean;

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

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

@Component@EnableSchedulingpublic class StartJob {   @Resource   private IDutyDefService dutyDefService;   @Autowired   public MySchedulerFactory mySchedulerFactory;   /**    * 启动定时器,10分钟执行一次,获取数据库最新数据    */   @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) {      }   }}

完成!!!!!