1、配置pom文件,添加quartz依赖
org.quartz-scheduler
quartz
2.2.3
org.quartz-scheduler
quartz-jobs
2.2.3
2、创建任务类
@Component
@EnableScheduling //开启对定时任务的支持
public class ScheduleTask implements Job {
private static final Logger logger = LoggerFactory.getLogger(ScheduleTask.class);
public void sendEmployeeNotice() {
logger.info("这是任务一");
// 具体任务逻辑
// ...
}
public void sendManagerNotice() {
logger.info("这是任务二");
// 具体任务逻辑
// ...
}
@Override
public void execute(JobExecutionContext jobExecutionContext) {
// 这里可以获取控制器绑定的值,实际应用中可以设置为某个活动的id,以便进行数据库操作
Object jobName = jobExecutionContext.getJobDetail().getKey();
logger.info("这是" + jobName + "任务" + new Date());
}
}
3、创建Quartz配置类,为任务配置jobDetail和trigger。
@Configuration
public class QuartzConfiguration {
// 配置定时任务1
@Bean(name = "firstJobDetail")
public MethodInvokingJobDetailFactoryBean firstJobDetail(ScheduleTask firstJob) {
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
/*
* 是否并发执行
* 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
* 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
*/
jobDetail.setConcurrent(false);
// 设置定时任务的名字
jobDetail.setName("SendSkillUpdateEmployeeNotice");
// 设置任务的分组,这些属性都可以在数据库中,在多任务的时候使用
jobDetail.setGroup("SendSkillUpdateEmployeeNotice");
// 为需要执行的实体类对应的对象
jobDetail.setTargetObject(firstJob);
/*
* sendEmployeeNotice为需要执行的方法
* 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的sendEmployeeNotice方法
*/
jobDetail.setTargetMethod("sendEmployeeNotice");
return jobDetail;
}
// 配置触发器1
@Bean(name = "firstTrigger")
public CronTriggerFactoryBean firstTrigger(JobDetail firstJobDetail) {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(firstJobDetail);
// 初始化的cron表达式--这里为每天9点执行
trigger.setCronExpression("0 0 9 * * ?");
// trigger的name
trigger.setName("trigger1");
return trigger;
}
// 配置定时任务2
@Bean(name = "secondJobDetail")
public MethodInvokingJobDetailFactoryBean secondJobDetail(ScheduleTask secondJob) {
MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean();
/*
* 是否并发执行
* 例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了,
* 如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行
*/
jobDetail.setConcurrent(false);
// 设置定时任务的名字
jobDetail.setName("SendSkillUpdateManagerNotice");
// 设置任务的分组,这些属性都可以在数据库中,在多任务的时候使用
jobDetail.setGroup("SendSkillUpdateManagerNotice");
// 为需要执行的实体类对应的对象
jobDetail.setTargetObject(secondJob);
/*
* sendManagerNotice为需要执行的方法
* 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的sendManagerNotice方法
*/
jobDetail.setTargetMethod("sendManagerNotice");
return jobDetail;
}
// 配置触发器2
@Bean(name = "secondTrigger")
public CronTriggerFactoryBean secondTrigger(JobDetail secondJobDetail) {
CronTriggerFactoryBean trigger = new CronTriggerFactoryBean();
trigger.setJobDetail(secondJobDetail);
// 初始化的cron表达式--每天10点执行
trigger.setCronExpression("0 0 10 * * ?");
// trigger的name
trigger.setName("trigger2");
return trigger;
}
/*
* 定义quartz调度工厂
*/
@Bean(name = "scheduler")
public SchedulerFactoryBean schedulerFactoryBean(Trigger firstTrigger, Trigger secondTrigger){
SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();
// 用于quartz集群,QuartzScheduler启动时更新已存在的job
factoryBean.setOverwriteExistingJobs(true);
// 延时启动,应用启动1秒后
factoryBean.setStartupDelay(1);
// 注册触发器
factoryBean.setTriggers(firstTrigger, secondTrigger);
return factoryBean;
}
}
4、动态修改执行周期
@Configuration
@EnableScheduling
@Component
public class ScheduleRefreshDatabase {
private static final Logger logger = LoggerFactory.getLogger(ScheduleRefreshDatabase.class);
@Autowired
private TimerRepository timerRepository;
private List timerConfigList;
@Resource(name = "firstTrigger")
private CronTrigger firstTrigger;
@Resource(name = "secondTrigger")
private CronTrigger secondTrigger;
@Resource(name = "scheduler")
private Scheduler scheduler;
@Scheduled(cron = "0 0 18 * * ?") // 每天18点查库,并根据查询结果决定是否重新设置定时任务
public void scheduleUpdateCronTrigger() throws SchedulerException {
timerConfigList = timerRepository.findAll();
if(null != timerConfigList && !timerConfigList.isEmpty()) {
for(TimerConfiguration config : timerConfigList) {
CronTrigger trigger = null;
switch (config.getTimerType()){
case "SendSkillUpdateEmployeeNotice":trigger = (CronTrigger) scheduler.getTrigger(firstTrigger.getKey());break;
case "SendSkillUpdateManagerNotice":trigger = (CronTrigger) scheduler.getTrigger(secondTrigger.getKey());break;
}
if (trigger == null) {
continue;
}
// 当前Trigger使用的
String currentCron = trigger.getCronExpression();
// 从数据库查询出来的
String searchCron = timerRepository.findTimerByType(config.getTimerType()).getCronExpression();
if (currentCron.equals(searchCron) || searchCron == null) {
// 如果当前使用的cron表达式和从数据库中查询出来的cron表达式一致,则不刷新任务
} else {
// 表达式调度构建器
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(searchCron);
// 按新的cronExpression表达式重新构建trigger
trigger = (CronTrigger) scheduler.getTrigger(trigger.getKey());
trigger = trigger.getTriggerBuilder().withIdentity(trigger.getKey()).withSchedule(scheduleBuilder).build();
// 按新的trigger重新设置job执行
scheduler.rescheduleJob(trigger.getKey(), trigger);
currentCron = searchCron;
logger.info("Update task corn::" + config.getTimerType() + "-" + currentCron);
}
}
}
}
}
5、实体类及数据库表
@Entity
@Table(name = "timer_configuration")
public class TimerConfiguration {
private static final long serialVersionUID = -4575153593917545670L;
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
@Column(name = "id", columnDefinition = "VARCHAR(255)")
private String id;
private String timerType;
private String cronExpression;
@CreatedDate
private Date createdTime;
@LastModifiedDate
private Date updatedTime;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTimerType() {
return timerType;
}
public void setTimerType(String timerType) {
this.timerType = timerType;
}
public String getCronExpression() {
return cronExpression;
}
public void setCronExpression(String cronExpression) {
this.cronExpression = cronExpression;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getUpdatedTime() {
return updatedTime;
}
public void setUpdatedTime(Date updatedTime) {
this.updatedTime = updatedTime;
}
}
public interface TimerRepository extends JpaRepository {
@Query("select timer from TimerConfiguration timer where timer.timerType=?1")
TimerConfiguration findTimerByType(String type);
}