quartz 項目整合Springboot
首先在項目中定時器是用的比較多的需求,如果不希望整合太多的第三方組件或者是項目中任務比較少完全可以使用spring自帶的任務Scheduled。
1,首先需要整合quartz
在POM文件中添加
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2,配置quartz 配置類
@Configuration
public class QuartzConfiguration {
//配置JobFactory
@Bean
public JobFactory jobFactory(ApplicationContext applicationContext) {
AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}
/**
* SchedulerFactoryBean這個類的真正作用提供了對org.quartz.Scheduler的創建與配置,並且會管理它的生命週期與Spring同步。
* org.quartz.Scheduler: 調度器。所有的調度都是由它控制。
* @param dataSource 爲SchedulerFactory配置數據源
* @param jobFactory 爲SchedulerFactory配置JobFactory
*/
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource, JobFactory jobFactory) throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
//可選,QuartzScheduler啓動時更新己存在的Job,這樣就不用每次修改targetObject後刪除qrtz_job_details表對應記錄
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(true); //設置自行啓動
factory.setDataSource(dataSource);
factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());
return factory;
}
//從quartz.properties文件中讀取Quartz配置屬性
@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}
//配置JobFactory,爲quartz作業添加自動連接支持
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;
}
}
}
配置quartz.properties,DataSource名稱
org.quartz.jobStore.dataSource = dataSource
#ID設置爲自動獲取 每一個必須不同 (所有調度器實例中是唯一的)
org.quartz.scheduler.instanceId=AUTO
#指定調度程序的主線程是否應該是守護線程
org.quartz.scheduler.makeSchedulerThreadDaemon=true
#ThreadPool實現的類名
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
#ThreadPool配置線程守護進程
org.quartz.threadPool.makeThreadsDaemons=true
#線程數量
org.quartz.threadPool.threadCount:20
#線程優先級
org.quartz.threadPool.threadPriority:5
#數據保存方式爲持久化
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
#StdJDBCDelegate說明支持集羣
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#quartz內部表的前綴
org.quartz.jobStore.tablePrefix=QRTZ_
#是否加入集羣
org.quartz.jobStore.isClustered=true
#容許的最大作業延長時間
org.quartz.jobStore.misfireThreshold=25000
3,引入數據庫
官網:http://www.quartz-scheduler.org/
下載下來找到自己合適的數據庫表,導入數據庫就可以了。
另外我們還需要建一個任務表,用來管理我們創建的任務。
4,開始啓動任務
定義JOB初始化方法,即從數據庫獲取job任務
package com.gd.app.job;
import com.gd.activiti.frame.quartz.service.JobService;
import com.gd.app.dao.JobEntityMapper;
import com.gd.app.pojo.JobEntity;
import lombok.extern.log4j.Log4j2;
import org.quartz.DisallowConcurrentExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.List;
@Component
@Log4j2
@DisallowConcurrentExecution
public class InitJob {
@Autowired
private JobService jobService;
@Resource
private JobEntityMapper jobEntityMapper;
@PostConstruct
public void initJob() throws Exception{
List<JobEntity> jobEntities = jobEntityMapper.selectAllJob();
jobEntities.forEach(jobEntity -> {
try {
jobService.addJob(entity);
} catch (Exception e) {
e.printStackTrace();
log.error("任務創建失敗");
}
});
}
}
查看具體處理類包含添加任務,暫停任務,啓動一次,重設任務等。。
@Service
@DisallowConcurrentExecution
public class JobServiceImpl implements JobService {
private final Scheduler scheduler;
Logger logger = LoggerFactory.getLogger(JobServiceImpl.class);
@Autowired
public JobServiceImpl(SchedulerFactoryBean schedulerFactoryBean) {
this.scheduler = schedulerFactoryBean.getScheduler();
}
@Override
public void addJob(JobEntity form) throws Exception {
if(scheduler.checkExists(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()))){
return;
}
// 啓動調度器
scheduler.start();
// 構建Job信息
JobDetail jobDetail = JobBuilder.newJob(JobUtil.getClass(form.getJobClassName()).getClass()).
withIdentity(form.getJobClassName(), form.getJobGroupName()).build();
// Cron表達式調度構建器(即任務執行的時間)
CronScheduleBuilder cron = CronScheduleBuilder.cronSchedule(form.getCronExpression());
//根據Cron表達式構建一個Trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(form.getJobClassName(), form.getJobGroupName()).withSchedule(cron).build();
try {
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
throw new ServiceErrorException("quartz.job.create");
}
}
@Override
public void deleteJob(JobEntity form) throws SchedulerException {
scheduler.pauseTrigger(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
scheduler.unscheduleJob(TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName()));
scheduler.deleteJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
}
@Override
public void startOnce(JobEntity form) throws Exception {
TriggerKey triggerKey = new TriggerKey(form.getJobClassName(), form.getJobGroupName());
Trigger trigger = scheduler.getTrigger(triggerKey);
scheduler.triggerJob(trigger.getJobKey());
}
@Override
public String getJobState(JobEntity form) throws SchedulerException {
TriggerKey triggerKey = new TriggerKey(form.getJobClassName(), form.getJobGroupName());
return scheduler.getTriggerState(triggerKey).name();
}
@Override
public void pauseJob(JobEntity form) throws SchedulerException {
scheduler.pauseJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
}
@Override
public void resumeJob(JobEntity form) throws SchedulerException {
scheduler.resumeJob(JobKey.jobKey(form.getJobClassName(), form.getJobGroupName()));
}
@Override
public void cronJob(JobEntity form) throws Exception {
try {
TriggerKey triggerKey = TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName());
// 表達式調度構建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(form.getCronExpression()).withMisfireHandlingInstructionDoNothing();
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 根據Cron表達式構建一個Trigger
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
// 按新的trigger重新設置job執行
scheduler.rescheduleJob(triggerKey, trigger);
} catch (SchedulerException e) {
throw new ServiceErrorException("quartz.job.create");
}
}
@Override
public void createJob(JobEntity form) throws Exception {
TriggerKey triggerKey = TriggerKey.triggerKey(form.getJobClassName(), form.getJobGroupName());
// 判斷定時任務是否存在
if (scheduler.checkExists(triggerKey)) {
cronJob(form);
} else {
addJob(form);
}
}
@Override
public JobEntity createJob(String oldCron, String newCron, String message, String className, String groupName) throws Exception {
JobEntity JobEntity = new JobEntity();
JobEntity.setJobClassName(className);
JobEntity.setJobGroupName(groupName);
if (CronExpression.isValidExpression(newCron)) {
// 記錄cron
oldCron = newCron;
} else {
logger.error(message);
}
JobEntity.setCronExpression(oldCron);
createJob(JobEntity);
return JobEntity;
}
}
看一下具體的實現效果