1、配置pom文件,添加quartz依赖
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.2.3</version> </dependency>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。
为了后期修改时间,这里需要为不同的任务配置不同的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<TimerConfiguration> 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; } } 数据库表如图所示 TimerRepository public interface TimerRepository extends JpaRepository<TimerConfiguration, String> { @Query("select timer from TimerConfiguration timer where timer.timerType=?1") TimerConfiguration findTimerByType(String type); }