Quartz key interface

  1. Scheduler – The main API for interacting with the Scheduler. (Control Job and trigger)
  2. Job – The interface implemented by the component that you want the scheduler to execute.
  3. JobDetail – Used to define instances of jobs. (Custom implementation)
  4. Trigger – A component that defines a plan to execute a given job. (Define trigger time and method)
  5. JobBuilder – Used to define/build JobDetail instances, used to define instances of jobs.
  6. TriggerBuilder – Used to define/build trigger instances.
  7. Listener the listener
    1. TriggerListeners and JobListeners are used on triggers, failures, and completions. (In most cases not, but when you need to create time notifications, you must explicitly use the listener notifier without the Job itself).
    2. SchedulerListeners are used to add jobs/triggers, delete jobs/triggers, serious errors in the scheduler, and disable dispatcher notifications.
Why do Job and trigger exist together
  1. Many task schedulers do not distinguish between jobs and triggers. Some schedulers simply define a job by an execution time and some job identifiers; Other schedulers combine the Quartz Job and Trigger objects. When we developed Quartz, we thought it made sense to separate scheduling from the tasks to be scheduled. From our point of view, this can bring many benefits.
  2. For example, after a Job is created, it can be saved in the Scheduler and is independent of Trigger. The same Job can have multiple triggers. Another benefit of this loose coupling is that when the triggers associated with the Job in the Scheduler all expire, the Job can be configured to be rescheduled later without redefining the Job; Also, Trigger can be modified or replaced without redefining the Job associated with it.
example
// Implement the Job interface and customize the execute method
  public class DumbJob implements Job {

    public DumbJob(a) {}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); }}/ / test
  // 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.141 f)
      .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);
Copy the code

Job status and concurrency

  1. There are a few other things to note about job state data (i.e., JobDataMap) and concurrency. You can add annotations to the Job class that affect the state and concurrency of the job.
  2. @ DisallowConcurrentExecution: to add the annotation to the job on the class, tell Quartz don’t execute concurrently in the same job definition (here refers to the specific job class) of multiple instances. Please pay attention to the wording here. This restriction is for the JobDetail, not the job class. But we thought we should put this annotation on the Job class because changes to the Job class often result in changes in its behavior.
  3. @ PersistJobDataAfterExecution: Add this annotation to the job class and tell Quartz to update the JobDataMap data in JobDetail so that the next time the job (i.e., JobDetail) is executed, The updated data is in JobDataMap, not the old data. Like @ DisallowConcurrentExecution notes, although the annotations are added in the job class, but its limit is used as an example of the job, rather than a job class. Annotations are carried by the Job class because the content of the Job class often affects its behavior state (for example, the Execute method of the Job class needs to explicitly “understand” its “state”).
  4. If you use the @ PersistJobDataAfterExecution annotations, we strongly recommend that you use the @ DisallowConcurrentExecution comment at the same time, because when the same job (JobDetail) are two instances of concurrent execution, due to the competition, The data stored in JobDataMap is likely to be indeterminate.

Integrate Quartz into Spring Boot

  1. Add the Quartz configuration to the project’s configuration file and then read it to Quartz. The configuration processor package of Spring Boot is used.
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
Copy the code
  1. Add configuration classes to your project. Here’s the @ConfigurationProperties annotation, which can inject properties in the application.yaml configuration file in conjunction with @Beans or @Component annotations that generate Spring beans
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;
    }

    /** * The real purpose of the SchedulerFactoryBean class is to provide the creation and configuration of org.Quartz.Scheduler and manage its lifecycle in sync with Spring. * Org. Quartz.Scheduler All scheduling is controlled by it. * *@paramJobFactory Configures jobFactory */ for the SchedulerFactory
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory) throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        // Optionally,QuartzScheduler starts to update existing jobs so that the corresponding records of the qrtz_job_details table are not deleted every time targetObject is changed
        factory.setOverwriteExistingJobs(true);
        factory.setAutoStartup(true);
        factory.setDataSource(dataSource);
        factory.setJobFactory(jobFactory);
        factory.setQuartzProperties(quartzProperties());
        return factory;
    }

    Read the Quartz configuration properties from the Quartz. Properties file
    @Bean
    public Properties quartzProperties(a) throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    // Configure JobFactory to add automatic connection support for Quartz jobs
    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);
            returnjob; }}}Copy the code

Reference:

  1. W3C Quartz Official Document