前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot 1.5.x 集成 Quartz 任务调度框架

SpringBoot 1.5.x 集成 Quartz 任务调度框架

作者头像
北漂的我
发布2019-12-24 15:47:18
1.4K0
发布2019-12-24 15:47:18
举报
文章被收录于专栏:北漂的我北漂的我

Quartz 有分 内存方式 和 数据库方式

内存方式任务信息保存在内存中, 停机会丢失, 需手动重新执行, 数据库方式: 任务信息保存在数据库中, 重点是支持集群.

内存方式 RAMJobStore 和 数据库方式 JobStoreTX, RAMJobStore 适合单机, 不支持集群, JobStoreTX 支持集群.

下面介绍的就是 JobStoreTX 数据库方式.

1. 添加主要的相关依赖, 其他依赖这里就不说了

代码语言:javascript
复制
<dependency>
	<groupId>org.quartz-scheduler</groupId>
	<artifactId>quartz</artifactId>
	<version>2.3.0</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context-support</artifactId>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-tx</artifactId>
</dependency>

2. quartz 的数据库表目前有 11 个, 可以下载官方包, 在官方包中可以找到建表语句, 对应不同的数据库有相应的sql语句.

配置文件 quartz.properties

代码语言:javascript
复制
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.instanceid=AUTO
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5
org.quartz.jobStore.misfireThreshold=2000
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.dataSource=myDS
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000
org.quartz.dataSource.myDS.driver=org.mariadb.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mariadb://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
#org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
#org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
org.quartz.dataSource.myDS.user=root 
org.quartz.dataSource.myDS.password=root
org.quartz.dataSource.myDS.maxConnections=5 
org.quartz.dataSource.myDS.validationQuery=select 0 from dual

3. JobFactory

代码语言:javascript
复制
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

@Configuration
public class JobFactory extends SpringBeanJobFactory {

	@Autowired
	private AutowireCapableBeanFactory autowireCapableBeanFactory;
	
	@Override
	protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
		Object createJobInstance = super.createJobInstance(bundle);
		autowireCapableBeanFactory.autowireBean(createJobInstance);
		return createJobInstance;
	}
}

4. QuartzConfig

代码语言:javascript
复制
import java.io.IOException;
import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {
	
	@Autowired
	private JobFactory jobFactory;
	
//	@Autowired
//	private DataSource dataSource;    // 如果使用application.properties中的数据源可以用这种方式
	
	@Bean
	public SchedulerFactoryBean myScheduler() throws IOException {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
//		schedulerFactoryBean.setDataSource(dataSource);                  // 使用 application.properties 中的数据源
		schedulerFactoryBean.setOverwriteExistingJobs(true);
		schedulerFactoryBean.setJobFactory(jobFactory);
		schedulerFactoryBean.setQuartzProperties(quartzProperties());    // 使用 quartz.properties 中的数据源
		schedulerFactoryBean.setSchedulerName("myScheduler");
		schedulerFactoryBean.setStartupDelay(2);// 延迟两秒启动
		schedulerFactoryBean.setAutoStartup(true);
		return schedulerFactoryBean;
	}
	
	@Bean
	public SchedulerFactoryBean myScheduler2() throws IOException {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
//		schedulerFactoryBean.setDataSource(dataSource);				   // 使用 application.properties 中的数据源
		schedulerFactoryBean.setOverwriteExistingJobs(true);
		schedulerFactoryBean.setJobFactory(jobFactory);
		schedulerFactoryBean.setQuartzProperties(quartzProperties());  // 使用 quartz.properties 中的数据源
		schedulerFactoryBean.setSchedulerName("myScheduler2");
		schedulerFactoryBean.setStartupDelay(2);// 延迟两秒启动
		schedulerFactoryBean.setAutoStartup(true);
		return schedulerFactoryBean;
	}
	
	private Properties quartzProperties() throws IOException {
		PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
		propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
		propertiesFactoryBean.afterPropertiesSet();
		Properties properties = propertiesFactoryBean.getObject();
		return properties;
	}
}

5. JobController

代码语言:javascript
复制
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.codingos.springboot.model.JobInfo;

@RestController
public class JobController {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private Scheduler myScheduler;   // 这个注入应该和 config 类中 @Bean 的方法名相同
	@Autowired
	private Scheduler myScheduler2;  // 这个注入应该和 config 类中 @Bean 的方法名相同
	
	
	/**
	 * 创建Job
	 */
	@PostMapping("/createJob")
	public void createJob(@RequestBody JobInfo jobInfo) {
		Scheduler scheduler = getScheduler(jobInfo.getSchedulerName());
		
		Class<? extends Job> jobClass = null;
		try {
			jobClass = (Class<? extends Job>) Class.forName(jobInfo.getJobClassName());
		} catch (ClassNotFoundException e) {
			logger.error("create Job " + jobInfo.getJobName() + " error: " + e.getMessage(), e);
		}
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
		JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).storeDurably().build();
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getCron());
		TriggerKey triggerKey = new TriggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());
		CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobDetail).withSchedule(scheduleBuilder).build();
		try {
			scheduler.scheduleJob(jobDetail, cronTrigger);
			scheduler.pauseJob(jobKey);   // 如果此处不暂停, 就会直接运行job
		} catch (SchedulerException e) {
			logger.error("create Job " + jobInfo.getJobName() + " error: " + e.getMessage(), e);
		}
	}
	
	@PostMapping("/jobStrat")
	public void jobStrat(@RequestBody JobInfo jobInfo) {
		Scheduler scheduler = getScheduler(jobInfo.getSchedulerName());
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
		try {
			scheduler.resumeJob(jobKey);  // 恢复执行job
		} catch (SchedulerException e) {
			logger.error("Job " + jobInfo.getJobName() + " start error: " + e.getMessage(), e);
		}
	}
	
	@PostMapping("/jobStop")
	public void jobStop(@RequestBody JobInfo jobInfo) {
		Scheduler scheduler = getScheduler(jobInfo.getSchedulerName());
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
		try {
			scheduler.pauseJob(jobKey);  // 暂停运行job
		} catch (SchedulerException e) {
			logger.error("Job " + jobInfo.getJobName() + " stop error: " + e.getMessage(), e);
		}
		
	}
	
	@PostMapping("/jobEdit")
	public void jobEdit(@RequestBody JobInfo jobInfo) {
		Scheduler scheduler = getScheduler(jobInfo.getSchedulerName());
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
		try {
			TriggerKey triggerKey = new TriggerKey(jobInfo.getTriggerName(), jobInfo.getTriggerGroup());
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobInfo.getCron());
			CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(triggerKey).forJob(jobKey).withSchedule(scheduleBuilder).build();
			scheduler.rescheduleJob(triggerKey, cronTrigger);  // 更新对应的 trigger
		} catch (SchedulerException e) {
			logger.error("Job " + jobInfo.getJobName() + " edit error: " + e.getMessage(), e);
		}
	}
	
	@PostMapping("/jobDelete")
	public void jobDelete(@RequestBody JobInfo jobInfo) {
		Scheduler scheduler = getScheduler(jobInfo.getSchedulerName());
		JobKey jobKey = new JobKey(jobInfo.getJobName(), jobInfo.getJobGroup());
		try {
			scheduler.deleteJob(jobKey);  // 删除job和对应的trigger 
		} catch (SchedulerException e) {
			logger.error("Job " + jobInfo.getJobName() + " stop error: " + e.getMessage(), e);
		}
	}
	
	private Scheduler getScheduler(String schedulerName) {
		Scheduler scheduler = null;
		switch (schedulerName) {
		case "myScheduler":
			scheduler = myScheduler;
			break;
		case "myScheduler2":
			scheduler = myScheduler2;
			break;
		default:
			break;
		}
		return scheduler;
	}
}

6. Job 类

代码语言:javascript
复制
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;

import com.codingos.springboot.service.Job1Service;

public class Job1 extends QuartzJobBean {
	
	@Autowired
	private Job1Service job1Service;

	@Override
	protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
		job1Service.service1();
	}
}

7. JobInfo 类

代码语言:javascript
复制
public class JobInfo {

	private String jobName;
	private String jobGroup;
	private String jobClassName;
	private String triggerName;
	private String triggerGroup;
	private String schedulerName;
	private String prevExecuteTime;
	private String nextExecuteTime;
	private String cron;
	private String triggerState;
	
	public JobInfo() {
	}

	public String getJobName() {
		return jobName;
	}

	public void setJobName(String jobName) {
		this.jobName = jobName;
	}

	public String getCron() {
		return cron;
	}

	public void setCron(String cron) {
		this.cron = cron;
	}

	public String getTriggerState() {
		return triggerState;
	}

	public void setTriggerState(String triggerState) {
		this.triggerState = triggerState;
	}

	public String getJobGroup() {
		return jobGroup;
	}

	public void setJobGroup(String jobGroup) {
		this.jobGroup = jobGroup;
	}

	public String getTriggerName() {
		return triggerName;
	}

	public void setTriggerName(String triggerName) {
		this.triggerName = triggerName;
	}

	public String getTriggerGroup() {
		return triggerGroup;
	}

	public void setTriggerGroup(String triggerGroup) {
		this.triggerGroup = triggerGroup;
	}

	public String getPrevExecuteTime() {
		return prevExecuteTime;
	}

	public void setPrevExecuteTime(String prevExecuteTime) {
		this.prevExecuteTime = prevExecuteTime;
	}

	public String getNextExecuteTime() {
		return nextExecuteTime;
	}

	public void setNextExecuteTime(String nextExecuteTime) {
		this.nextExecuteTime = nextExecuteTime;
	}

	public String getJobClassName() {
		return jobClassName;
	}

	public void setJobClassName(String jobClassName) {
		this.jobClassName = jobClassName;
	}

	public String getSchedulerName() {
		return schedulerName;
	}

	public void setSchedulerName(String schedulerName) {
		this.schedulerName = schedulerName;
	}
}

最后, 说一下, 如果是 SpringBoot 2.x 集成 Quartz 框架, 添加依赖就非常方便了

代码语言:javascript
复制
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档