springboot集成quartz并实现持久化

引入jar

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-quartz</artifactId>
	</dependency>

方式一:手动装置
配置QuartzSchedulerConfig 类


import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.quartz.ee.servlet.QuartzInitializerListener;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.jrf.core.quartz.factory.JobFactory;

/**
 * quartz定时任务配置
 * @author Administrator
 *
 */
@EnableScheduling
@Configuration
public class QuartzSchedulerConfig {
	
	// 配置文件路径
	private static final String QUARTZ_CONFIG = "/quartz.properties";
    
	/**
     * 配置任务工厂实例
     * @param applicationContext spring上下文实例
     * @return
     */
	@Bean
	public JobFactory jobFactory(ApplicationContext applicationContext) {
		
		/**
		 * 采用自定义任务工厂 整合spring实例来完成构建任务 see {@link AutowiringSpringBeanJobFactory}
		 */
		JobFactory jobFactory = new JobFactory();
		jobFactory.setApplicationContext(applicationContext);
		return jobFactory;
	}
    

    /**
     * 配置任务调度器
     * 使用项目数据源作为quartz数据源
     * @param jobFactory 自定义配置任务工厂
     * @param dataSource 数据源实例
     * @return
     * @throws IOException 
     * @throws Exception
     */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory, DataSource dataSource) throws IOException{
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		// 将spring管理job自定义工厂交由调度器维护
		schedulerFactoryBean.setJobFactory(jobFactory);
		// 设置覆盖已存在的任务
		schedulerFactoryBean.setOverwriteExistingJobs(true);
		// 项目启动完成后,等待10秒后开始执行调度器初始化
		schedulerFactoryBean.setStartupDelay(10);
		// 设置调度器自动运行
		schedulerFactoryBean.setAutoStartup(true);
		// 设置数据源,使用与项目统一数据源
		schedulerFactoryBean.setDataSource(dataSource);
		// 设置上下文spring bean name
		schedulerFactoryBean.setApplicationContextSchedulerContextKey("applicationContext");
		schedulerFactoryBean.setQuartzProperties(quartzProperties());
		return schedulerFactoryBean;
	}
	
	/**
	 * 从quartz.properties文件中读取Quartz配置属性
	 * @return
	 * @throws IOException
	 */
    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_CONFIG));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    /**
     * 初始化监听器
     * 
     * @return
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }
    
}

自定义job工厂,将spring管理job自定义工厂交由调度器维护


import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

/**
 * 创建job 实例工厂,解决spring注入问题,如果使用默认会导致spring的@Autowired 无法注入问题
 *
 */
public class JobFactory extends SpringBeanJobFactory implements ApplicationContextAware  {
    
    /**
     *AutowireCapableBeanFactory接口是BeanFactory的子类
     *可以连接和填充那些生命周期不被Spring管理的已存在的bean实例     
     */
	private transient AutowireCapableBeanFactory beanFactory;

	@Override
    public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    /**
     * 将job实例交给spring ioc托管
     * 我们在job实例实现类内可以直接使用spring注入的调用被spring ioc管理的实例
     * @param bundle
     * @return
     * @throws Exception
     */
    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        /**
         * 将job实例交付给spring ioc
         */
        beanFactory.autowireBean(job);
        return job;
    }
}

编写Quartz任务调度业务工具类


import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Quartz任务调度管理
 */
@Component
public class QuartzManager {

	@Autowired
	private Scheduler scheduler;
	
	/**
	 * 添加一个定时Cron任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param cron 表达式参考quartz说明文档
	 */
	public void addCronJob(Long id, Class jobClass,String cron) {
		addCronJob(id, jobClass, cron, new HashMap<String, Object>());
	}
	
	/**
	 * /**
	 * 添加一个定时Cron任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param cron 表达式参考quartz说明文档
	 * @param params 参数内容
	 */
	public void addCronJob(Long id, Class jobClass,String cron, Map<String,Object> params) {
		String jobName = "QuartzJob@"+id;
        String jobGroupName = "QuartzJobGroup@"+id;
        String triggerName = "QuartzTrigger@"+id;
        String triggerGroupName = "QuartzTriggerGroup@"+id;
        addCronJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron, params);
	}
	
	
	/**
     * @Description: 添加一个定时Cron任务
     *
     * @param jobName
     *            任务名
     * @param jobGroupName
     *            任务组名
     * @param triggerName
     *            触发器名
     * @param triggerGroupName
     *            触发器组名
     * @param jobClass
     *            任务
     * @param cron
     *            时间设置,参考quartz说明文档
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public void addCronJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass,
                           String cron, Map<String,Object> params) {
        try {
            if(checkExists(jobName, jobGroupName, triggerName, triggerGroupName)) {
              //先移除后添加
                removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
            }
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            if(params != null && params.size() > 0){
                for(String key :params.keySet()){
                    jobDetail.getJobDataMap().put(key,params.get(key));
                }
            }
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger)triggerBuilder.build();

            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);

        }
    }
    
    /**
	 * 添加一个定时Simple任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param startTime 任务开始时间
	 */
	public void addSimpleExecuteOnceJob(Long id, Class jobClass,Date startTime) {
		addSimpleExecuteOnceJob(id, jobClass, startTime, new HashMap<String, Object>());
	}
	
	/**
	 * /**
	 * 添加一个定时Simple任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param startTime 任务开始时间
	 * @param params 参数内容
	 */
	public void addSimpleExecuteOnceJob(Long id, Class jobClass,Date startTime, Map<String,Object> params) {
		String jobName = "QuartzJob@"+id;
        String jobGroupName = "QuartzJobGroup@"+id;
        String triggerName = "QuartzTrigger@"+id;
        String triggerGroupName = "QuartzTriggerGroup@"+id;
        addSimpleExecuteOnceJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, startTime, params);
	}
    
    /**
     * addSimpleExecuteOnceJob 执行一次
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @param jobClass
     * @param startTime
     */
    public void addSimpleExecuteOnceJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
        Class jobClass, Date startTime, Map<String,Object> params) {
        try {
            if(checkExists(jobName, jobGroupName, triggerName, triggerGroupName)) {
                //先移除后添加
                  removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
              }
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            if(params != null && params.size() > 0){
                for(String key :params.keySet()){
                    jobDetail.getJobDataMap().put(key,params.get(key));
                }
            }
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器
            SimpleScheduleBuilder simpleSchedule = SimpleScheduleBuilder.simpleSchedule();
            // 触发器时间设定
            triggerBuilder.withSchedule(simpleSchedule);
            triggerBuilder.startAt(startTime);
            SimpleTrigger trigger = (SimpleTrigger)triggerBuilder.build();
            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);

        }
    }
    
    /**
	 * 添加一个定时Simple任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param startTime 任务开始时间
	 */
	public void addSimpleRepeatedExecutionJob(Long id, Class jobClass,Date startTime, int repeatCount, int repeatInterval) {
		addSimpleRepeatedExecutionJob(id, jobClass, startTime, repeatCount, repeatInterval,new HashMap<String, Object>());
	}
	
	/**
	 * /**
	 * 添加一个定时Simple任务
	 * @param id 任务id
	 * @param jobClass 任务实现类
	 * @param startTime 任务开始时间
	 * @param params 参数内容
	 */
	public void addSimpleRepeatedExecutionJob(Long id, Class jobClass,Date startTime, int repeatCount, int repeatInterval, Map<String,Object> params) {
		String jobName = "QuartzJob@"+id;
        String jobGroupName = "QuartzJobGroup@"+id;
        String triggerName = "QuartzTrigger@"+id;
        String triggerGroupName = "QuartzTriggerGroup@"+id;
        addSimpleRepeatedExecutionJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, startTime, repeatCount, repeatInterval, params);
	}
	
	
    
    /**
     * addSimpleRepeatedExecutionJob 重复执行,建议使用 Cron模式
     * @param jobName
     *            任务名
     * @param jobGroupName
     *            任务组名
     * @param triggerName
     *            触发器名
     * @param triggerGroupName
     *            触发器组名
     * @param jobClass
     *            任务
     * @param startTime 执行开始时间
     * @param repeatCount 重复次数 0表示执行一次
     * @param repeatInterval 时间间隔 
     */
    public void addSimpleRepeatedExecutionJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
        Class jobClass, Date startTime, int repeatCount, int repeatInterval, Map<String,Object> params) {
        try {
            if(checkExists(jobName, jobGroupName, triggerName, triggerGroupName)) {
                //先移除后添加
                  removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
              }
            // 任务名,任务组,任务执行类
            JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build();
            if(params != null && params.size() > 0){
                for(String key :params.keySet()){
                    jobDetail.getJobDataMap().put(key,params.get(key));
                }
            }
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(triggerName, triggerGroupName);
            triggerBuilder.startNow();
            // 触发器
            SimpleScheduleBuilder simpleSchedule = SimpleScheduleBuilder.simpleSchedule();
            //重复时间
            simpleSchedule.withIntervalInSeconds(repeatInterval);
            //重复次数
            simpleSchedule.withRepeatCount(repeatCount);
            // 触发器时间设定
            triggerBuilder.withSchedule(simpleSchedule);
            triggerBuilder.startAt(startTime);
            SimpleTrigger trigger = (SimpleTrigger)triggerBuilder.build();
            // 调度容器设置JobDetail和Trigger
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动
            if (!scheduler.isShutdown()) {
                scheduler.start();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);

        }
    }

    /**
     * @Description: 修改一个任务的触发时间
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     *            触发器名
     * @param triggerGroupName
     *            触发器组名
     * @param cron
     *            时间设置,参考quartz说明文档
     */
    public void modifyCronJobTime(String jobName, String jobGroupName, String triggerName, String triggerGroupName,
        String cron) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }

            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                System.out.println("任务:" + jobName + "被修改");
                /** 方式一 :调用 rescheduleJob 开始 */
                /* // 触发器
                 TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                 // 触发器名,触发器组
                 triggerBuilder.withIdentity(triggerName, triggerGroupName);
                 triggerBuilder.startNow();
                 // 触发器时间设定
                 triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                 // 创建Trigger对象
                 trigger = (CronTrigger) triggerBuilder.build();
                 // 方式一 :修改一个任务的触发时间
                 scheduler.rescheduleJob(triggerKey, trigger);*/
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job */
                JobDetail jobDetail = scheduler.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                Class<? extends Job> jobClass = jobDetail.getJobClass();
                removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                addCronJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron,null);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description: 移除一个任务
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);// 停止触发器
            scheduler.unscheduleJob(triggerKey);// 移除触发器
            scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName));// 删除任务
            
            
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    /**
     * 检查是否存在
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     * @return
     */
    public boolean checkExists(String jobName, String jobGroupName, String triggerName, String triggerGroupName) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            JobKey jobKey = new JobKey(jobName, jobGroupName);
            boolean triggerCheck = scheduler.checkExists(triggerKey);
            boolean jobCheck = scheduler.checkExists(jobKey);
            return triggerCheck || jobCheck;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @Description:启动所有定时任务
     */
    public void startJobs() {
        try {
            scheduler.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:关闭所有定时任务
     */
    public void shutdownJobs() {
        try {
            if (!scheduler.isShutdown()) {
                scheduler.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取当前正在执行的任务
     * 
     * @return
     */
    public boolean getCurrentJobs(String name) {
        try {
            List<JobExecutionContext> jobContexts = scheduler.getCurrentlyExecutingJobs();
            for (JobExecutionContext context : jobContexts) {
                if (name.equals(context.getTrigger().getJobKey().getName())) {
                    return true;
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return false;
    }

}

quartz.properties 文件

#调度标识名 集群中每一个实例都必须使用相同的名称
org.quartz.scheduler.instanceName = quartzScheduler
#调度器实例编号自动生成,每个实例不能不能相同
org.quartz.scheduler.instanceId = AUTO
#开启分布式部署,集群
org.quartz.jobStore.isClustered = true
#分布式节点有效性检查时间间隔,单位:毫秒,默认值是15000
org.quartz.jobStore.clusterCheckinInterval = 2000
#远程管理相关的配置,全部关闭
org.quartz.scheduler.rmi.export: false
org.quartz.scheduler.rmi.proxy: false
org.quartz.scheduler.wrapJobExecutionInUserTransaction: false
#实例化ThreadPool时,使用的线程类为SimpleThreadPool(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
##并发个数,指定线程数,至少为1(无默认值)(一般设置为1-100之间的的整数合适)
org.quartz.threadPool.threadCount = 10
##设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority = 5
#org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
#容许的最大作业延长时间,最大能忍受的触发超时时间,如果超过则认为“失误”,不敢再内存中还是数据中都要配置
org.quartz.jobStore.misfireThreshold = 6000
#持久化方式配置
# 默认存储在内存中,保存job和Trigger的状态信息到内存中的类
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
#数据库方式
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#持久化方式配置数据驱动,MySQL数据库
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#quartz相关数据表前缀名
org.quartz.jobStore.tablePrefix = QRTZ_
 
#数据库别名 随便取
#org.quartz.jobStore.dataSource = qzDS
#org.quartz.dataSource.qzDS.driver = com.mysql.jdbc.Driver
#org.quartz.dataSource.qzDS.URL = jdbc:mysql://127.0.0.1:3306/quartzdb?useSSL=false&useUnicode=true&characterEncoding=UTF-8
#org.quartz.dataSource.qzDS.user = root
#org.quartz.dataSource.qzDS.password = 123456
#org.quartz.dataSource.qzDS.maxConnections = 10
#org.quartz.dataSource.qzDS.acquireIncrement=1

方式二:依赖springboot
yml配置模式

spring:
  jackson:
    date-format: yyyy-MM-dd
    time-zone: GMT+8
    serialization:
      write-dates-as-timestamps: false
  datasource : 
    url : jdbc:mysql://192.168.2.200:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username : root
    password : 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    #通过这句配置将druid连接池引入到我们的配置中,spring会尽可能判断类型是什么,然后根据情况去匹配驱动类。
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
        initial-size: 5  # 初始化大小
        min-idle: 5  # 最小
        max-active: 100  # 最大
        max-wait: 60000  # 配置获取连接等待超时的时间
        time-between-eviction-runs-millis: 60000  # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        min-evictable-idle-time-millis: 300000  # 指定一个空闲连接最少空闲多久后可被清除,单位是毫秒
        validationQuery: select 'x'
        test-while-idle: true  # 当连接空闲时,是否执行连接测试
        test-on-borrow: false  # 当从连接池借用连接时,是否测试该连接
        test-on-return: false  # 在连接归还到连接池时是否测试该连接
        filters: config,wall,stat  # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        poolPreparedStatements: true # 打开PSCache,并且指定每个连接上PSCache的大小
        maxPoolPreparedStatementPerConnectionSize: 20
        maxOpenPreparedStatements: 20
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.slowSqlMillis=200;druid.stat.logSlowSql=true;config.decrypt=false
         # 合并多个DruidDataSource的监控数据
        #use-global-data-source-stat: true
  quartz:
    #相关属性配置
    properties:
      org:
        quartz:
          scheduler:
            instanceName: quartzScheduler
            instanceId: AUTO
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: false
            clusterCheckinInterval: 10000
            useProperties: false
            dataSource: quartzDs
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 10
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
    #数据库方式
    job-store-type: JDBC
    #初始化表结构
    jdbc:
      initialize-schema: NEVER

quartz的数据源问题,如果我们没有@QuartzDataSource修饰的数据源,那么默认情况下就是我们的工程数据源,springboot会将工程数据源设置给quartz

spring注入问题

quartz job无需注入到spring容器中,但quartz job中是可以注入spring容器中的常规bean的,当然还可以注入jab data map中的属性值;

springboot覆写了quartz的jobFactory,使得quartz在调用jobFactory创建job实例的时候,能够将spring容器的bean注入到job中,AutowireCapableBeanJobFactory中createJobInstance方法如下

@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
    Object jobInstance = super.createJobInstance(bundle);    // 通过反射实例化job,并将JobDataMap中属性注入到job实例中
    this.beanFactory.autowireBean(jobInstance);                // 注入job依赖的spring中的bean    
    this.beanFactory.initializeBean(jobInstance, null);
    return jobInstance;
}

如上面的 JobFactory 类

job存储方式

JobStore是负责跟踪调度器(scheduler)中所有的工作数据:作业任务、触发器、日历等。我们无需在我们的代码中直接使用JobStore实例,只需要通过配置信息告知Quartz该用哪个JobStore即可。quartz的JobStore有两种:RAMJobStore、JDBCJobStore,通过名字我们也能猜到这两者之间的区别与优缺点。
img
至于选择哪种方式,就看哪种方式更契合我们的业务需求,没有绝对的选择谁与不选择谁,只看哪种更合适。据我的理解和工作中的应用,内存方式用的更多;实际应用中,我们往往只是持久化我们自定义的基础job(不是quartz的job)到数据库,应用启动的时候加载基础job到quartz中,进行quartz job的初始化,quartz的job相关信息全部存储在RAM中;一旦应用停止,quartz的job信息全部丢失,但这影响不大,可以通过我们的自定义job进行quartz job的恢复,但是恢复的quartz job是原始状态,如果需要实时保存quartz job的状态,那就需要另外设计或者用JDBC方式了。

quartz mysql 表文件

DROP TABLE
IF EXISTS QRTZ_FIRED_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;

DROP TABLE
IF EXISTS QRTZ_SCHEDULER_STATE;

DROP TABLE
IF EXISTS QRTZ_LOCKS;

DROP TABLE
IF EXISTS QRTZ_SIMPLE_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_SIMPROP_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_CRON_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_BLOB_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_TRIGGERS;

DROP TABLE
IF EXISTS QRTZ_JOB_DETAILS;

DROP TABLE
IF EXISTS QRTZ_CALENDARS;

CREATE TABLE QRTZ_JOB_DETAILS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	JOB_NAME VARCHAR (200) NOT NULL,
	JOB_GROUP VARCHAR (200) NOT NULL,
	DESCRIPTION VARCHAR (250) NULL,
	JOB_CLASS_NAME VARCHAR (250) NOT NULL,
	IS_DURABLE VARCHAR (1) NOT NULL,
	IS_NONCONCURRENT VARCHAR (1) NOT NULL,
	IS_UPDATE_DATA VARCHAR (1) NOT NULL,
	REQUESTS_RECOVERY VARCHAR (1) NOT NULL,
	JOB_DATA BLOB NULL,
	PRIMARY KEY (
		SCHED_NAME,
		JOB_NAME,
		JOB_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	JOB_NAME VARCHAR (200) NOT NULL,
	JOB_GROUP VARCHAR (200) NOT NULL,
	DESCRIPTION VARCHAR (250) NULL,
	NEXT_FIRE_TIME BIGINT (13) NULL,
	PREV_FIRE_TIME BIGINT (13) NULL,
	PRIORITY INTEGER NULL,
	TRIGGER_STATE VARCHAR (16) NOT NULL,
	TRIGGER_TYPE VARCHAR (8) NOT NULL,
	START_TIME BIGINT (13) NOT NULL,
	END_TIME BIGINT (13) NULL,
	CALENDAR_NAME VARCHAR (200) NULL,
	MISFIRE_INSTR SMALLINT (2) NULL,
	JOB_DATA BLOB NULL,
	PRIMARY KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	FOREIGN KEY (
		SCHED_NAME,
		JOB_NAME,
		JOB_GROUP
	) REFERENCES QRTZ_JOB_DETAILS (
		SCHED_NAME,
		JOB_NAME,
		JOB_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	REPEAT_COUNT BIGINT (7) NOT NULL,
	REPEAT_INTERVAL BIGINT (12) NOT NULL,
	TIMES_TRIGGERED BIGINT (10) NOT NULL,
	PRIMARY KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	FOREIGN KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	) REFERENCES QRTZ_TRIGGERS (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_CRON_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	CRON_EXPRESSION VARCHAR (120) NOT NULL,
	TIME_ZONE_ID VARCHAR (80),
	PRIMARY KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	FOREIGN KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	) REFERENCES QRTZ_TRIGGERS (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_SIMPROP_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	STR_PROP_1 VARCHAR (512) NULL,
	STR_PROP_2 VARCHAR (512) NULL,
	STR_PROP_3 VARCHAR (512) NULL,
	INT_PROP_1 INT NULL,
	INT_PROP_2 INT NULL,
	LONG_PROP_1 BIGINT NULL,
	LONG_PROP_2 BIGINT NULL,
	DEC_PROP_1 NUMERIC (13, 4) NULL,
	DEC_PROP_2 NUMERIC (13, 4) NULL,
	BOOL_PROP_1 VARCHAR (1) NULL,
	BOOL_PROP_2 VARCHAR (1) NULL,
	PRIMARY KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	FOREIGN KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	) REFERENCES QRTZ_TRIGGERS (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_BLOB_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	BLOB_DATA BLOB NULL,
	PRIMARY KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	INDEX (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	),
	FOREIGN KEY (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	) REFERENCES QRTZ_TRIGGERS (
		SCHED_NAME,
		TRIGGER_NAME,
		TRIGGER_GROUP
	)
) ENGINE = INNODB;

CREATE TABLE QRTZ_CALENDARS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	CALENDAR_NAME VARCHAR (200) NOT NULL,
	CALENDAR BLOB NOT NULL,
	PRIMARY KEY (SCHED_NAME, CALENDAR_NAME)
) ENGINE = INNODB;

CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP)
) ENGINE = INNODB;

CREATE TABLE QRTZ_FIRED_TRIGGERS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	ENTRY_ID VARCHAR (95) NOT NULL,
	TRIGGER_NAME VARCHAR (200) NOT NULL,
	TRIGGER_GROUP VARCHAR (200) NOT NULL,
	INSTANCE_NAME VARCHAR (200) NOT NULL,
	FIRED_TIME BIGINT (13) NOT NULL,
	SCHED_TIME BIGINT (13) NOT NULL,
	PRIORITY INTEGER NOT NULL,
	STATE VARCHAR (16) NOT NULL,
	JOB_NAME VARCHAR (200) NULL,
	JOB_GROUP VARCHAR (200) NULL,
	IS_NONCONCURRENT VARCHAR (1) NULL,
	REQUESTS_RECOVERY VARCHAR (1) NULL,
	PRIMARY KEY (SCHED_NAME, ENTRY_ID)
) ENGINE = INNODB;

CREATE TABLE QRTZ_SCHEDULER_STATE (
	SCHED_NAME VARCHAR (120) NOT NULL,
	INSTANCE_NAME VARCHAR (200) NOT NULL,
	LAST_CHECKIN_TIME BIGINT (13) NOT NULL,
	CHECKIN_INTERVAL BIGINT (13) NOT NULL,
	PRIMARY KEY (SCHED_NAME, INSTANCE_NAME)
) ENGINE = INNODB;

CREATE TABLE QRTZ_LOCKS (
	SCHED_NAME VARCHAR (120) NOT NULL,
	LOCK_NAME VARCHAR (40) NOT NULL,
	PRIMARY KEY (SCHED_NAME, LOCK_NAME)
) ENGINE = INNODB;

CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS (
	SCHED_NAME,
	REQUESTS_RECOVERY
);

CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS (SCHED_NAME, JOB_GROUP);

CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS (
	SCHED_NAME,
	JOB_NAME,
	JOB_GROUP
);

CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS (SCHED_NAME, JOB_GROUP);

CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS (SCHED_NAME, CALENDAR_NAME);

CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);

CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE);

CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS (
	SCHED_NAME,
	TRIGGER_NAME,
	TRIGGER_GROUP,
	TRIGGER_STATE
);

CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS (
	SCHED_NAME,
	TRIGGER_GROUP,
	TRIGGER_STATE
);

CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS (SCHED_NAME, NEXT_FIRE_TIME);

CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS (
	SCHED_NAME,
	TRIGGER_STATE,
	NEXT_FIRE_TIME
);

CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS (
	SCHED_NAME,
	MISFIRE_INSTR,
	NEXT_FIRE_TIME
);

CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS (
	SCHED_NAME,
	MISFIRE_INSTR,
	NEXT_FIRE_TIME,
	TRIGGER_STATE
);

CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS (
	SCHED_NAME,
	MISFIRE_INSTR,
	NEXT_FIRE_TIME,
	TRIGGER_GROUP,
	TRIGGER_STATE
);

CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME);

CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS (
	SCHED_NAME,
	INSTANCE_NAME,
	REQUESTS_RECOVERY
);

CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS (
	SCHED_NAME,
	JOB_NAME,
	JOB_GROUP
);

CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_GROUP);

CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS (
	SCHED_NAME,
	TRIGGER_NAME,
	TRIGGER_GROUP
);

CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_GROUP);

COMMIT;


  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值