Spring Boot整合Quartz定时任务框架

了解Quartz

Quartz启动器

 <!-- quartz启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

Quartz框架的使用思路

1)job - 任务 - 你要做什么事?

2)Trigger - 触发器 - 你什么时候去做?

3)Scheduler - 任务调度 - 你什么时候需要去做什么事?

Spring Boot整合Quartz定时任务框架

Scheduler接口

​ Scheduler翻译成调度器,Quartz通过调度器来注册、暂停、删除Trigger和JobDetail。Scheduler还拥有一个SchedulerContext,顾名思义就是上下文,通过SchedulerContext我们可以获取到触发器和任务的一些信息。

Trigger接口

​ Trigger可以翻译成触发器,通过cron表达式或是SimpleScheduleBuilder等类,指定任务执行的周期。系统时间走到触发器指定的时间的时候,触发器就会触发任务的执行。

JobDetail接口

​ Job接口是真正需要执行的任务。JobDetail接口相当于将Job接口包装了一下,Trigger和Scheduler实际用到的都是JobDetail。

SpringBoot集成Quartz

第一种方式

建表

​ 我选择将定时任务的信息保存在数据库中,优点是显而易见的,定时任务不会因为系统的崩溃而丢失。

​ 建表的sql语句在Quartz的github中可以找到,里面有针对每一种常用数据库的sql语句,具体地址是:Quartz数据库建表sql

配置quartz

spring:
  quartz:
    # 将任务等保存化到数据库
    job-store-type: jdbc
    # 程序结束时会等待quartz相关的内容结束
    wait-for-jobs-to-complete-on-shutdown: true
    # QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
    overwrite-existing-jobs: true
    properties:
      org:
        quartz:
          # scheduler相关
          scheduler:
            # scheduler的实例名
            instanceName: scheduler
            instanceId: AUTO
          # 持久化相关
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            # 表示数据库中相关表是QRTZ_开头的
            tablePrefix: QRTZ_
            useProperties: false
          # 线程池相关
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            # 线程数
            threadCount: 10
            # 线程优先级
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true
  datasource:
    url: jdbc:mysql://localhost:3306/ysh?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  type-aliases-package: com.ysh.pojo
  mapper-locations: classpath:dao/*.xml

注册周期性的定时任务

​ 周期性任务一般是固定的,但是一直会执行的任务。

/**
 *Quartz的相关配置,注册JobDetail和Trigger
 */
@Configuration
public class QuartzConfig {

    @Bean
    public JobDetail jobDetail() {
        JobDetail jobDetail = JobBuilder.newJob(JobTest.class)
                .withIdentity("job_test", "job_test")
                .storeDurably()
                .build();
        return jobDetail;
    }

    @Bean
    public Trigger trigger() {
        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(jobDetail())
                .withIdentity("job_test", "job_test")
                .startNow()
                // 每隔两秒执行一次
                .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
                .build();
        return trigger;
    }
}

可以写一个类来实现Job接口做具体的任务

@Component
public class JobTest extends QuartzJobBean {
    @Autowired
    UserService userService;

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext)
            throws JobExecutionException {
        // 任务的具体逻辑
        System.out.println("开始了");
        userService.addUser();
    }
}

解决注入问题

​ 问题:UserService是被spring管理,而JobTest这个Job是Quartz通过反射创建的,即使加了注解@Component,这个StartOfDayJob对象也不会被注册到ioc容器中,更不可能实现依赖的自动装配。

解决:自定义一个JobFactory,继承AdaptableJobFactory,然后重写其中的createJobInstance方法以达到注入的目的

@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {

	//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
	@Autowired
	private AutowireCapableBeanFactory autowireCapableBeanFactory;

	/**
	 * 该方法将需要实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
	 */
	@Override
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
		Object obj = super.createJobInstance(bundle);
		//将obj对象添加Spring IOC容器中,并完成注入
		this.autowireCapableBeanFactory.autowireBean(obj);
		return obj;
	}
}

注册无周期性的定时任务

​ 无周期性任务一般是不定时的,一次性的,而且不具有周期性。

  • Job类需要获取到一些数据用于任务的执行;
  • 任务执行完成后删除Job和Trigger。

代码:暂无。。。

另一种方式

Quartz配置类

/**
 * Quartz配置类
 */
@Configuration
public class QuartzConfig {

	
	/**
	 * 1.创建Job对象
	 */
	@Bean
	public JobDetailFactoryBean jobDetailFactoryBean(){
		JobDetailFactoryBean factory = new JobDetailFactoryBean();
		//关联我们自己的Job类
		factory.setJobClass(MyJob.class);
		return factory;
	}
	
	/**
	 * Cron Trigger
	 */
   @Bean
	public CronTriggerFactoryBean cronTriggerFactoryBean(JobDetailFactoryBean 
                                                         jobDetailFactoryBean){
		CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
		factory.setJobDetail(jobDetailFactoryBean.getObject());
		//设置触发时间
		factory.setCronExpression("0/2 * * * * ?");
		return factory;
	}
	
	/**
	 * 3.创建Scheduler对象
	 */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean 
                                                     cronTriggerFactoryBean){
		SchedulerFactoryBean factory = new SchedulerFactoryBean();
		//关联trigger
		factory.setTriggers(cronTriggerFactoryBean.getObject());
		
		return factory;
	}
}

Job中注入service

public class MyJob implements Job {
	@Autowired
	private UsersService usersService;

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		System.out.println("Execute...."+new Date());
		usersService.addUser();
	}
}

解决注入问题

@Component("myAdaptableJobFactory")
public class MyAdaptableJobFactory extends AdaptableJobFactory {

	//AutowireCapableBeanFactory 可以将一个对象添加到SpringIOC容器中,并且完成该对象注入
	@Autowired
	private AutowireCapableBeanFactory autowireCapableBeanFactory;

	/**
	 * 该方法将需要实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
	 */
	@Override
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
		Object obj = super.createJobInstance(bundle);
		//将obj对象添加Spring IOC容器中,并完成注入
		this.autowireCapableBeanFactory.autowireBean(obj);
		return obj;
	}
}

修改QuartzConfig类

/**
	 * 3.创建Scheduler对象
	 */
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(CronTriggerFactoryBean 
    			cronTriggerFactoryBean, MyAdaptableJobFactory myAdaptableJobFactory){
		SchedulerFactoryBean factory = new SchedulerFactoryBean();
		//关联trigger
		factory.setTriggers(cronTriggerFactoryBean.getObject());
		factory.setJobFactory(myAdaptableJobFactory);
		return factory;
	}
上一篇:【Quartz】Cron表达式


下一篇:WPF 调试触发器