Springboot整合quartz框架(附代码)

以前使用springmvc项目时,整合quartz框架多用配置文件的形式,使用springboot后,可以完全用注解来整合quartz。

首先创建一个简单的maven项目,然后修改pom配置文件,引入需要用到的依赖

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.3.RELEASE</version>
	<relativePath /> <!-- lookup parent from repository -->
</parent>
	
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<!-- quartz -->
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-quartz</artifactId>
	</dependency>
</dependencies>

然后我们创建QuartzApplication类,这个类是 springboot 程序的启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class QuartzApplication {
	public static void main(String[] args) {
		SpringApplication.run(QuartzApplication.class, args);
	}
}

接着创建application.yml,该文件为spring的配置文件,文件非常简单,只定义了一个 quartz cron 表达式

quartz:
  #秒,分钟,时,日,月,周,年  
  expression: 
    print: 0/5 * * * * ? *

这个表达式表示job将会每隔5秒执行一次,我们在程序启动后将表达式的值映射到 QuartzCronKey 中 , 这样方便我们在各个类中使用表达式的值。

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @title quartz cron 表达式配置bean
 * @author gavin
 * @date 2019年5月10日
 */
@Component
@ConfigurationProperties(prefix="quartz.expression")
public class QuartzCronKey {
	
	private String print;

	public String getPrint() {
		return print;
	}

	public void setPrint(String print) {
		this.print = print;
	}
}

接下来我们创建PrintJob类,定义定时任务的业务逻辑,execute方法会每隔5秒打印一次系统当前时间

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

@DisallowConcurrentExecution // 防止当任务执行时间(假如5秒)长于任务设定的间隔时间(假如3秒),本次任务还未执行完毕又开始下一次任务调度。
public class PrintJob implements Job{

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		Date currentTime = new Date();
		DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		System.out.println("打印当前时间:" + format.format(currentTime));
	}
	
}

其中 @DisallowConcurrentExecution 注解的作用是,防止当任务执行时间(例如5秒)长于任务设定的间隔时间(例如3秒),本次任务还未执行完毕又开始下一次任务调度。

然后我们创建 PrintTask 类,我们可以在这里配置 JobDetailFactoryBean 和 CronTriggerFactoryBean

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;

import com.gavin.quartz.QuartzCronKey;
import com.gavin.quartz.job.PrintJob;

@Configuration
public class PrintTask {

	@Autowired
	private QuartzCronKey quartzCronKey;
	
	
	@Bean(name="printFactory")
	public JobDetailFactoryBean jobDetailFactoryBean() {
		// 生成jobDetail
		JobDetailFactoryBean factory = new JobDetailFactoryBean();
		// 设置对应的Job类型
		factory.setJobClass(PrintJob.class);
		return factory;
	}
	
	
	@Bean("printTrigger")
	public CronTriggerFactoryBean cronTriggerFactoryBean(){
		CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
		// 设置jobDetail
		factory.setJobDetail(jobDetailFactoryBean().getObject());
		factory.setStartDelay(1000);
		// 定时任务cron表达式配置
		factory.setCronExpression(quartzCronKey.getPrint());
		return factory;
	}
}

除了以上几个类之外,我们还需要定义一个 AutowiringSpringBeanJobFactory 类,这个类用来将Quartz中的job自动注入spring容器中,这样我们的定时任务才能被 spring 容器加载。

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

/**
 * @title AutowiringSpringBeanJobFactory类,这个类用来Quartz中的job自动注入spring容器托管的对象
 * @author gavin
 * @date 2019年5月10日
 */
public final class AutowiringSpringBeanJobFactory 
	extends SpringBeanJobFactory 
	implements ApplicationContextAware{
	
	private transient 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;
	}
	
}

最后我们通过定义 QuartzConfig 类来配置所有的 trigger 触发器

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {

	@Autowired
	@Qualifier("printTrigger")
	private CronTriggerFactoryBean printTrigger;
	
	/**
	 * @title Quartz中的job自动注入spring容器托管的对象
	 * @author gavin
	 * @date 2019年5月10日
	 * @return
	 */
	@Bean
	public AutowiringSpringBeanJobFactory autoWiringSpringBeanJobFactory() {
		return new AutowiringSpringBeanJobFactory();
	}
	
	
	@Bean
	public SchedulerFactoryBean schedulerFactoryBean() throws Exception{
		SchedulerFactoryBean scheduler  = new SchedulerFactoryBean();
		// 配置Spring注入的Job类 
		scheduler.setJobFactory(autoWiringSpringBeanJobFactory());
		// 配置定时器,参数接收Trigger数组,可接收多个trigger
		scheduler.setTriggers(
			printTrigger.getObject()
		);
		scheduler.setAutoStartup(true);
		return scheduler;
	}
	
}

其中 scheduler.setJobFactory(trigger…)方法接收的是一个数组,也意味着如果我们想配置多个触发器,只要在该方法中添加即可。

所有配置完毕,我们运行 QuartzApplication 中的main方法,可以看到每隔5秒控制台会打印当前时间信息,说明 quartz 整合成功 !
图1.控制台日志打印
如需查看完整代码,请访问github获取: https://github.com/liaozq0426/-spring-quartz.git

猜你喜欢

转载自blog.csdn.net/u012693016/article/details/94400581