1、Quartz的3个基本要素
- Scheduler:调度器。所有的调度都是由它控制。
- Trigger: 触发器。决定什么时候来执行任务。
- JobDetail & Job: JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。使用JobDetail + Job而不是Job,这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。
1、添加QuartZ依赖
<!-- quartz依赖 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<!-- 该依赖必加,里面有sping对schedule的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.4.RELEASE</version>
</dependency>
2、注入Bean
@Configuration
public class QuartzConfigration{
@Bean(name = "jobDetail")
public MethodInvokingJobDetailFactoryBean detailFactoryBean(WsdlTask task) {
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
/*
* 是否并发执行
* 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
* 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
*/
jobDetail.setConcurrent(false);
jobDetail.setName("wsdl-getRawMaterial");
jobDetail.setGroup("wsdl");
jobDetail.setTargetObject(task);
jobDetail.setTargetMethod("getRawMaterial");
return jobDetail;
}
/**
* attention:
* Details:配置定时任务的触发器,也就是什么时候触发执行定时任务
*/
@Bean(name = "jobTrigger")
public CronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) {
CronTriggerFactoryBean tigger = new CronTriggerFactoryBean();
tigger.setJobDetail(Objects.requireNonNull(jobDetail.getObject()));
tigger.setCronExpression("0/2 * * * * ? ");
tigger.setName("wsdl-getRawMaterial");
return tigger;
}
/**
* attention:
* Details:定义quartz调度工厂
*/
@Bean(name = "scheduler")
public SchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
// 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
bean.setOverwriteExistingJobs(true);
// 延时启动,应用启动1秒后
bean.setStartupDelay(1);
// 注册触发器
bean.setTriggers(cronJobTrigger);
return bean;
}
}
3、数据库控制
@Component
public class ScheduleRefresh {
@Resource(name = "jobTrigger")
private CronTrigger cronTrigger;
@Resource(name = "scheduler")
private Scheduler scheduler;
private final JPAQueryFactory jpaFactory;
private final QSystemConfig qSystemConfig;
private static final String ON = "on";
private static final String OFF = "off";
public ScheduleRefresh(BaseDao dao) {
this.jpaFactory = new JPAQueryFactory(dao.getEntityManager());
this.qSystemConfig = QSystemConfig.systemConfig;
}
/**
* @description: 每隔5s查库,并根据查询结果决定是否重新设置定时任务
* @params:
* @return:
* @auther: WZH
* @date: 2019/12/16 17:00
*/
@Scheduled(fixedRate = 5000)
public void scheduleUpdateCronTrigger() throws SchedulerException {
TriggerKey triggerKey = cronTrigger.getKey();
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
String rawMaterialOn = "rawMaterialOn";
String searchOn = jpaFactory.select(qSystemConfig.value).from(qSystemConfig).where(qSystemConfig.name.eq(rawMaterialOn)).fetchFirst();
Trigger.TriggerState state = scheduler.getTriggerState(triggerKey);
if(state== Trigger.TriggerState.NORMAL&& OFF.equals(searchOn)){
//暂停定时器
System.out.println(state);
System.out.println("暂停定时器--------------------");
scheduler.pauseTrigger(triggerKey);
}else if (state==Trigger.TriggerState.PAUSED&&ON.equals(searchOn)){
//恢复定时器
System.out.println(state);
System.out.println("恢复定时器--------------------");
scheduler.resumeTrigger(triggerKey);
}
if(state==Trigger.TriggerState.NORMAL&&ON.equals(searchOn)){
//当前执行周期
String currentCron = trigger.getCronExpression();
//从数据库查询出来的
String rawMaterialCron = "rawMaterialCron";
String searchCron = jpaFactory.select(qSystemConfig.value).from(qSystemConfig).where(qSystemConfig.name.eq(rawMaterialCron)).fetchFirst();
if (!currentCron.equals(searchCron)) {
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
// 按新的cronExpression表达式重新构建trigger
trigger = (CronTrigger) scheduler.getTrigger(cronTrigger.getKey());
trigger = trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey())
.withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(cronTrigger.getKey(), trigger);
}
}
}
}
4、具体业务类
@Service
public class WsdlTask {
public void getRawMaterial(){
System.out.println("测试QuartZ---------"+new Date());
}
}
5、Quartz中Job和Trigger的执行状态
STATE_BLOCKED 4 阻塞
STATE_COMPLETE 2 完成
STATE_ERROR 3 错误
STATE_NONE -1 不存在
STATE_NORMAL 0 正常
STATE_PAUSED 1 暂停