Spring boot Quartz with example

When it comes to scheduling jobs in a java application, Quartz is the first tool that comes into consideration.

Quartz is job scheduler backed up by most popular RDBMSes.
It is really convenient and gets integrated with spring quite easy.

In order to create the quartz schema you have to download the quartz distribution and extract the folder located in quartz-2.2.3/docs/dbTables/

Choose the quartz schema according to the database that you use.
In our case we will use a local h2 database therefore I will use the tables_h2.sql schema.

POM

<dependencies>
     <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
    </dependency>
</dependencies>	 

application.properties

quartz.enabled=true
samplejob.frequency=2000

quartz.properties

org.quartz.scheduler.instanceName=spring-boot-quartz-demo
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=5
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=60000
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000	

SchedulerConfig

	@Configuration
	@ConditionalOnProperty(name = "quartz.enabled")
	public class SchedulerConfig {
	
	    private static JobDetailFactoryBean createJobDetail(Class jobClass) {
	        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
	        factoryBean.setJobClass(jobClass);
	        // job has to be durable to be stored in DB:
	        factoryBean.setDurability(true);
	        return factoryBean;
	    }
	
	    private static SimpleTriggerFactoryBean createTrigger(JobDetail jobDetail, long pollFrequencyMs) {
	        SimpleTriggerFactoryBean factoryBean = new SimpleTriggerFactoryBean();
	        factoryBean.setJobDetail(jobDetail);
	        factoryBean.setStartDelay(0L);
	        factoryBean.setRepeatInterval(pollFrequencyMs);
	        factoryBean.setRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY);
	        // in case of misfire, ignore all missed triggers and continue :
	        factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_RESCHEDULE_NEXT_WITH_REMAINING_COUNT);
	        return factoryBean;
	    }
	
	    // Use this method for creating cron triggers instead of simple triggers:
	    private static CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression) {
	        CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
	        factoryBean.setJobDetail(jobDetail);
	        factoryBean.setCronExpression(cronExpression);
	        factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
	        return factoryBean;
	    }
	
	    // injecting SpringLiquibase to ensure liquibase is already initialized and created the quartz tables:
	    @Bean
	    public JobFactory jobFactory(ApplicationContext applicationContext) {
	        AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
	        jobFactory.setApplicationContext(applicationContext);
	        return jobFactory;
	    }
	
	    @Bean
	    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory, @Qualifier("sampleJobTrigger") Trigger sampleJobTrigger) throws IOException {
	        SchedulerFactoryBean factory = new SchedulerFactoryBean();
	        // this allows to update triggers in DB when updating settings in config file:
	        factory.setOverwriteExistingJobs(true);
	        factory.setDataSource(dataSource);
	        factory.setJobFactory(jobFactory);
	        factory.setQuartzProperties(quartzProperties());
	
	        return factory;
	    }
	
	    @Bean
	    public Properties quartzProperties() throws IOException {
	        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
	        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
	        propertiesFactoryBean.afterPropertiesSet();
	        return propertiesFactoryBean.getObject();
	    }
	
	    @Bean
	    public JobDetailFactoryBean sampleJobDetail() {
	        return createJobDetail(SampleJob.class);
	    }
	
	    @Bean(name = "sampleJobTrigger")
	    public SimpleTriggerFactoryBean sampleJobTrigger(@Qualifier("sampleJobDetail") JobDetail jobDetail, @Value("${samplejob.frequency}") long frequency) {
	        return createTrigger(jobDetail, frequency);
	    }
	
	}	
}

SampleJob

public class SampleJob implements Job {

    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        System.out.printf("SampleJob 执行 - 时间: " + System.currentTimeMillis());
    }
}

JobController

@Controller
@RequestMapping(value = "jobController")
@Api(value = "定时任务管理")
public class JobController {
    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    private SchedulerFactoryBean schedulerFactory;

    @RequestMapping(value = "initJob", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "初始化定时任务", notes = "根据URL的num来初始化定时任务")
    public ResponseMessage initJob() {

        Scheduler scheduler = schedulerFactory.getScheduler();
        JobDetail job = newJob(CleanUseFlowJob.class)
                .withIdentity("清空Pro用户使用流量", "Pro组")
                .build();


        Trigger trigger = newTrigger()
                .withIdentity("清空Pro用户使用流量", "Pro组")
                .startNow()
                .withSchedule(
                        cronSchedule("0 0 1 1 * ?")//每月1号凌晨1点执行
                ).build();
        // Tell quartz to schedule the job using our trigger
        try {
            scheduler.scheduleJob(job, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }

 

RESOURCES:

 

Spring boot quartz example

 

spring boot official