SpringBoot集成Quartz 开始正常执行,一段时间后任务不执行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot集成Quartz 开始正常执行,一段时间后任务不执行相关的知识,希望对你有一定的参考价值。
参考技术A PS: 最近项目需要定时进行数据汇总,引入了Quartz之后发现,开始的时候任务可以执行,一段时间后后台看不到报错,但是任务却不执行。SpringBoot 1.5.x 集成 Quartz 任务调度框架
Quartz 有分 内存方式 和 数据库方式
内存方式任务信息保存在内存中, 停机会丢失, 需手动重新执行, 数据库方式: 任务信息保存在数据库中, 重点是支持集群.
内存方式 RAMJobStore 和 数据库方式 JobStoreTX, RAMJobStore 适合单机, 不支持集群, JobStoreTX 支持集群.
下面介绍的就是 JobStoreTX 数据库方式.
1. 添加主要的相关依赖, 其他依赖这里就不说了
<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
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
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
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
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 类
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 类
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 框架, 添加依赖就非常方便了
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
来源:湖北网站优化
以上是关于SpringBoot集成Quartz 开始正常执行,一段时间后任务不执行的主要内容,如果未能解决你的问题,请参考以下文章