quartz + springboot 注解_SpringBoot2.0集成Quartz定时任务(持久化到数据库)

前言

之前写过一篇spring整合quartz的过程的文章,但是配置比较繁琐,而且持久化脚本需要手动生成到数据库,比较笨拙;

现在大多数项目都使用了springboot,所以本文主要讲springboot与quartz的完美整合,简化配置、持久化数据并自定义quartz数据源。

38a67fb47537205c471fcadee047b5a1.png

正文

一、增加依赖

我们使用的spring-boot-starter-quartz,所以不用显示指定版本号

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

二、yml配置信息

spring:   # 数据库配置  datasource:    type: com.alibaba.druid.pool.DruidDataSource    dynamic:      primary: master #设置默认的数据源或者数据源组,默认值即为master      datasource:        master:          url: xxx          driver-class-name: com.mysql.cj.jdbc.Driver          username: root          password: xxx        quartz:          url: xxx          driver-class-name: com.mysql.cj.jdbc.Driver          username: root          password: xxx  # quartz定时任务  quartz:    jdbc:      # 初始化Quartz表结构,项目第一次启动配置程always,然后改成never 否则已生成的job会被初始化掉      initialize-schema: never    #设置quartz任务的数据持久化方式,默认是内存方式    job-store-type: jdbc    properties:      org:        quartz:          scheduler:            instanceName: etlCleanScheduler            instanceId: AUTO          jobStore:            class: org.quartz.impl.jdbcjobstore.JobStoreTX            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate            tablePrefix: QRTZ_  #Quartz表前缀            isClustered: true            clusterCheckinInterval: 10000            useProperties: false          threadPool:            class: org.quartz.simpl.SimpleThreadPool            #线程数 一个任务使用一个线程            threadCount: 100            threadPriority: 5            threadsInheritContextClassLoaderOfInitializingThread: true

自定生成表结构,需要配置如下信息:

spring.quartz.jdbc.initialize-schema: alwaysspring.quartz.job-store-type: jdbc

项目启动后生成的表信息

c26f729ae8bcacb10e4d8b8dde5faa3e.png

三、自定义数据源

其实到第二部配置就已经结束了,但是很多时候,我们希望quartz的数据源和项目的业务数据源是分离的,那我们需要再配置下数据源。

在启动类下增加以下代码:

/** * 主数据源 * @return */@Primary@Bean@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.master")public DruidDataSource druidDataSource() {    return new DruidDataSource();}/** * 配置Quartz独立数据源的配置 */@Bean@QuartzDataSource@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource.quartz")public DataSource quartzDataSource(){    return new DruidDataSource();}
1c96bb18ae2c1c594a5e7df9ec01e575.gif

注意:

438e8e6ba25d81c690569a66aad393ea.png

​一定要增加主数据源,并加上@primary注解,不然业务用的数据源会切换到quartz数据源

四、定时任务逻辑封装

QuartzService定时器操作业务类,需要增加数据源切换注解。

/** * quartz逻辑 * @author gourd */@Service@DS("quartz")public class QuartzServiceImpl implements QuartzService {    @Autowired    private Scheduler scheduler;    @PostConstruct    public void startScheduler() {        try {            scheduler.start();        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 增加一个job     *      * @param jobClass     *            任务实现类     * @param jobName     *            任务名称     * @param jobGroupName     *            任务组名     * @param jobTime     *            时间表达式 (这是每隔多少秒为一次任务)     * @param jobTimes     *            运行的次数 (<0:表示不限次数)     * @param jobData     *            参数     */    @Override    public void addJob(Class extends QuartzJobBean> jobClass, String jobName, String jobGroupName, int jobTime,                       int jobTimes, Map jobData) {        try {            // 任务名称和组构成任务key            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)                    .build();            // 设置job参数            if(jobData!= null && jobData.size()>0){                jobDetail.getJobDataMap().putAll(jobData);            }            // 使用simpleTrigger规则            Trigger trigger = null;            if (jobTimes < 0) {                trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))                        .startNow().build();            } else {                trigger = TriggerBuilder                        .newTrigger().withIdentity(jobName, jobGroupName).withSchedule(SimpleScheduleBuilder                                .repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))                        .startNow().build();            }            scheduler.scheduleJob(jobDetail, trigger);        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 增加一个job     *      * @param jobClass     *            任务实现类     * @param jobName     *            任务名称(建议唯一)     * @param jobGroupName     *            任务组名     * @param jobTime     *            时间表达式 (如:0/5 * * * * ? )     * @param jobData     *            参数     */    @Override    public void addJob(Class extends QuartzJobBean> jobClass, String jobName, String jobGroupName, String jobTime, Map jobData) {        try {            // 创建jobDetail实例,绑定Job实现类            // 指明job的名称,所在组的名称,以及绑定job类            // 任务名称和组构成任务key            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName)                    .build();            // 设置job参数            if(jobData!= null && jobData.size()>0){                jobDetail.getJobDataMap().putAll(jobData);            }            // 定义调度触发规则            // 使用cornTrigger规则            // 触发器key            Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)                    .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).startNow().build();            // 把作业和触发器注册到任务调度中            scheduler.scheduleJob(jobDetail, trigger);        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 修改 一个job的 时间表达式     *      * @param jobName     * @param jobGroupName     * @param jobTime     */    @Override    public void updateJob(String jobName, String jobGroupName, String jobTime) {        try {            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime)).build();            // 重启触发器            scheduler.rescheduleJob(triggerKey, trigger);        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 删除任务一个job     *      * @param jobName     *            任务名称     * @param jobGroupName     *            任务组名     */    @Override    public void deleteJob(String jobName, String jobGroupName) {        try {            scheduler.deleteJob(new JobKey(jobName, jobGroupName));        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 暂停一个job     *      * @param jobName     * @param jobGroupName     */    @Override    public void pauseJob(String jobName, String jobGroupName) {        try {            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);            scheduler.pauseJob(jobKey);        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 恢复一个job     *      * @param jobName     * @param jobGroupName     */    @Override    public void resumeJob(String jobName, String jobGroupName) {        try {            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);            scheduler.resumeJob(jobKey);        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 立即执行一个job     *      * @param jobName     * @param jobGroupName     */    @Override    public void runAJobNow(String jobName, String jobGroupName) {        try {            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);            scheduler.triggerJob(jobKey);        } catch (SchedulerException e) {            e.printStackTrace();        }    }    /**     * 获取所有计划中的任务列表     *      * @return     */    @Override    public List> queryAllJob() {        List> jobList = null;        try {            GroupMatcher matcher = GroupMatcher.anyJobGroup();            Set jobKeys = scheduler.getJobKeys(matcher);            jobList = new ArrayList>();            for (JobKey jobKey : jobKeys) {                List extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);                for (Trigger trigger : triggers) {                    Map map = new HashMap<>();                    map.put("jobName", jobKey.getName());                    map.put("jobGroupName", jobKey.getGroup());                    map.put("description", "触发器:" + trigger.getKey());                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());                    map.put("jobStatus", triggerState.name());                    if (trigger instanceof CronTrigger) {                        CronTrigger cronTrigger = (CronTrigger) trigger;                        String cronExpression = cronTrigger.getCronExpression();                        map.put("jobTime", cronExpression);                    }                    jobList.add(map);                }            }        } catch (SchedulerException e) {            e.printStackTrace();        }        return jobList;    }    /**     * 获取所有正在运行的job     *      * @return     */    @Override    public List> queryRunJob() {        List> jobList = null;        try {            List executingJobs = scheduler.getCurrentlyExecutingJobs();            jobList = new ArrayList>(executingJobs.size());            for (JobExecutionContext executingJob : executingJobs) {                Map map = new HashMap();                JobDetail jobDetail = executingJob.getJobDetail();                JobKey jobKey = jobDetail.getKey();                Trigger trigger = executingJob.getTrigger();                map.put("jobName", jobKey.getName());                map.put("jobGroupName", jobKey.getGroup());                map.put("description", "触发器:" + trigger.getKey());                Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());                map.put("jobStatus", triggerState.name());                if (trigger instanceof CronTrigger) {                    CronTrigger cronTrigger = (CronTrigger) trigger;                    String cronExpression = cronTrigger.getCronExpression();                    map.put("jobTime", cronExpression);                }                jobList.add(map);            }        } catch (SchedulerException e) {            e.printStackTrace();        }        return jobList;    }}
1c96bb18ae2c1c594a5e7df9ec01e575.gif

具体的Job类

import org.quartz.JobDataMap;import org.quartz.JobExecutionContext;import org.quartz.JobExecutionException;import org.springframework.scheduling.quartz.QuartzJobBean;import org.springframework.stereotype.Component;import java.util.Date;/** * job触发时间 * @author gourd */@Componentpublic class Job extends QuartzJobBean {    @Override    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {        System.out.println(new Date() + "    job执行");        // 获取参数        JobDataMap jobDataMap = arg0.getJobDetail().getJobDataMap();        // 业务逻辑 ...    }}

cron工具类,将date 转换成cron格式

import java.text.SimpleDateFormat;import java.util.Date; public class QuartzCronDateUtils {/***      *  功能描述:日期转换cron表达式时间格式     * @param date      * @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss      * @return      */      public static String formatDateByPattern(Date date,String dateFormat){          SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);          String formatTimeStr = null;          if (date != null) {              formatTimeStr = sdf.format(date);          }          return formatTimeStr;      }      /***      * convert Date to cron ,eg.  "14 01 17 22 07 ? 2017"      * @param date:时间点      * @return      */      public static String getCron(Date  date){        String dateFormat="ss mm HH dd MM ? yyyy";          return formatDateByPattern(date,dateFormat);      }  }

五、测试

@Autowiredprivate QuartzService quartzService;@PostMapping("/addjob")@ApiOperation(value = "增加定时任务")public void addJob() {    Map map = new HashMap(2);    map.put("id",1L);    // 先删除,再新增加    quartzService.deleteJob("job", "test");    quartzService.addJob(Job.class, "job", "test", "0/30 * * * * ?",map);}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值