zoukankan      html  css  js  c++  java
  • 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 - 任务调度 - 你什么时候需要去做什么事?

    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;
    	}
    
    我等的船还不来
  • 相关阅读:
    16条很有用的Chrome浏览器命令
    通用测试用例
    Vue中@click、@click.stop和@click.prevet用法
    Vue事件的函数传参
    Vue事件的基本用法
    vue中v-on和v-bind的区别
    Vue中数据的双向绑定方法
    v-once用法
    v-clock、v-text、v-html和v-pre详解
    IDEA给已有项目添加maven依赖
  • 原文地址:https://www.cnblogs.com/lxs1204/p/14274277.html
Copyright © 2011-2022 走看看