美文网首页
定时任务:Quartz - 集成到Spring boot

定时任务:Quartz - 集成到Spring boot

作者: minute_5 | 来源:发表于2019-08-03 16:30 被阅读0次

    Quartz关键接口

    1. Scheduler - 与调度程序交互的主要API。(控制Job与trigger)
    2. Job - 由希望调度程序执行的组件实现的接口。
    3. JobDetail - 用于定义作业的实例。(自定义实现)
    4. Trigger(即触发器) - 定义执行给定作业的计划的组件。(定义触发时间与方式)
    5. JobBuilder - 用于定义/构建JobDetail实例,用于定义作业的实例。
    6. TriggerBuilder - 用于定义/构建触发器实例。
    7. 监听器listener
      1. TriggerListeners和JobListeners用于触发器触发,触发失灵,与触发完成的情况。(大多数情况下不使用,但当需要创建时间通知时,不需要Job本身就必须明确地使用listener通知程序)。
      2. SchedulerListeners用于添加job/触发器,删除job/触发器,调度程序中的严重错误,关闭调度程序的通知时。
    为什么会同时存在Job,与trigger
    1. 很多任务调度器并不区分Job和Trigger。有些调度器只是简单地通过一个执行时间和一些job标识符来定义一个Job;其它的一些调度器将Quartz的Job和Trigger对象合二为一。在开发Quartz的时候,我们认为将调度和要调度的任务分离是合理的。在我们看来,这可以带来很多好处。
    2. 例如,Job被创建后,可以保存在Scheduler中,与Trigger是独立的,同一个Job可以有多个Trigger;这种松耦合的另一个好处是,当与Scheduler中的Job关联的trigger都过期时,可以配置Job稍后被重新调度,而不用重新定义Job;还有,可以修改或者替换Trigger,而不用重新定义与之关联的Job。
    例子
    //实现Job接口,自定义实现execute方法
      public class DumbJob implements Job {
    
        public DumbJob() {
        }
    
        public void execute(JobExecutionContext context)
          throws JobExecutionException
        {
          JobKey key = context.getJobDetail().getKey();
    
          JobDataMap dataMap = context.getJobDetail().getJobDataMap();
    
          String jobSays = dataMap.getString("jobSays");
          float myFloatValue = dataMap.getFloat("myFloatValue");
    
          System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
        }
      }
    
      // 测试
      // define the job and tie it to our DumbJob class
      JobDetail job = newJob(DumbJob.class)
          .withIdentity("myJob", "group1") // name "myJob", group "group1"
          .usingJobData("jobSays", "Hello World!")
          .usingJobData("myFloatValue", 3.141f)
          .build();
      // Trigger the job to run now, and then every 40 seconds
      Trigger trigger = newTrigger()
          .withIdentity("myTrigger", "group1")
          .startNow()
          .withSchedule(simpleSchedule()
              .withIntervalInSeconds(40)
              .repeatForever())
          .build();
      // Tell quartz to schedule the job using our trigger
      sched.scheduleJob(job, trigger);
    

    Job状态与并发

    1. 关于job的状态数据(即JobDataMap)和并发性,还有一些地方需要注意。在job类上可以加入一些注解,这些注解会影响job的状态和并发性。
    2. @DisallowConcurrentExecution:将该注解加到job类上,告诉Quartz不要并发地执行同一个job定义(这里指特定的job类)的多个实例。请注意这里的用词。该限制是针对JobDetail的,而不是job类的。但是我们认为(在设计Quartz的时候)应该将该注解放在job类上,因为job类的改变经常会导致其行为发生变化。
    3. @PersistJobDataAfterExecution:将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该job(即JobDetail)在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据。和 @DisallowConcurrentExecution注解一样,尽管注解是加在job类上的,但其限制作用是针对job实例的,而不是job类的。由job类来承载注解,是因为job类的内容经常会影响其行为状态(比如,job类的execute方法需要显式地“理解”其”状态“)。
    4. 如果你使用了@PersistJobDataAfterExecution注解,我们强烈建议你同时使用@DisallowConcurrentExecution注解,因为当同一个job(JobDetail)的两个实例被并发执行时,由于竞争,JobDataMap中存储的数据很可能是不确定的。

    将Quartz集成到Spring boot中

    1. 在项目的配置文件中加上Quartz配置,然后再读取给Quartz。这里使用的是spring boot的configuration-processor包。
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
    
    1. 在项目中添加配置类,这里说一下@ConfigurationProperties注解,它可以注入在application.yaml配置文件中的属性,和@Bean 或者 @Component 能生成spring bean 的注解结合起来使用
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import java.util.HashMap;
    import java.util.Map;
    
    @ConfigurationProperties("zongw.TestQuartz")
    public class TestQuartzProperties {
        @Bean
        public JobFactory jobFactory(ApplicationContext applicationContext) {
            AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
            jobFactory.setApplicationContext(applicationContext);
            return jobFactory;
        }
    
        /**
         * SchedulerFactoryBean这个类的真正作用提供了对org.quartz.Scheduler的创建与配置,并且会管理它的生命周期与Spring同步。
         * org.quartz.Scheduler: 调度器。所有的调度都是由它控制。
         * 
         * @param jobFactory 为SchedulerFactory配置JobFactory
         */
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory) throws IOException {
            SchedulerFactoryBean factory = new SchedulerFactoryBean();
            //可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
            factory.setOverwriteExistingJobs(true);
            factory.setAutoStartup(true);
            factory.setDataSource(dataSource);
            factory.setJobFactory(jobFactory);
            factory.setQuartzProperties(quartzProperties());
            return factory;
        }
    
        //从quartz.properties文件中读取Quartz配置属性
        @Bean
        public Properties quartzProperties() throws IOException {
            PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
            propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
            propertiesFactoryBean.afterPropertiesSet();
            return propertiesFactoryBean.getObject();
        }
    
        //配置JobFactory,为quartz作业添加自动连接支持
        public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
                ApplicationContextAware {
            private AutowireCapableBeanFactory beanFactory;
    
            @Override
            public void setApplicationContext(final ApplicationContext context) {
                beanFactory = context.getAutowireCapableBeanFactory();
            }
    
            @Override
            protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
                final Object job = super.createJobInstance(bundle);
                beanFactory.autowireBean(job);
                return job;
            }
        }
    }
    

    参考:

    1. 《W3C Quartz官方文档》

    相关文章

      网友评论

          本文标题:定时任务:Quartz - 集成到Spring boot

          本文链接:https://www.haomeiwen.com/subject/vvbjdctx.html