- 在实际的项目应用中会应用到很多的定时任务,在项目开启的时候就可以自动执行一系列的任务,以及每隔固定时间就去执行定义好的任务
我了解到可以实现这种作业调度的是实现方式有三种:
- 第一种: springboot自带的Schedule
- 第二种:Quartz
- 第三种: XXLJOB(暂时先不解释)
方式一: 使用springboot自带的Schedule
- 导入POM依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
- 创建定时任务:
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @introduce: schedule定时任务
* @outhor: 赫于富
* @DATE: 2020年9月25日16:41:49
**/
@Component
public class ScheduleTest {
private static final Logger logger = LoggerFactory.getLogger(ScheduleTest.class);
@Scheduled(cron="0 0/2 8-20 * * ?")
public void executeFileDownLoadTask() {
// 间隔2分钟,执行工单上传任务
Thread current = Thread.currentThread();
System.out.println("定时任务1:"+current.getId());
logger.info("ScheduledTest.executeFileDownLoadTask 定时任务1:"+current.getId()+ ",name:"+current.getName());
}
@Scheduled(cron="0 0/1 8-20 * * ?")
public void executeUploadTask() {
// 间隔1分钟,执行工单上传任务
Thread current = Thread.currentThread();
System.out.println("定时任务2:"+current.getId());
logger.info("ScheduledTest.executeUploadTask 定时任务2:"+current.getId() + ",name:"+current.getName());
}
@Scheduled(cron="0 0/3 5-23 * * ?")
public void executeUploadBackTask() {
// 间隔3分钟,执行工单上传任务
Thread current = Thread.currentThread();
System.out.println("定时任务3:"+current.getId());
logger.info("ScheduledTest.executeUploadBackTask 定时任务3:"+current.getId()+ ",name:"+current.getName());
}
}
- 在启动类上开启定时任务
@SpringBootApplication
@EnableScheduling
public class SpringbootQuartzApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 运行结果:
参数说明:
@Scheduled 参数可以接受两种定时的设置,一种是我们常用的 corn="*/6 * * * * ?"
另一种是fixedRate=6000,两种都可以表示固定周期执行定时任务
- @Scheduled(fixedRate = 6000):上一次开始执行时间点之后 6 秒再执行。
- @Scheduled(fixedDelay = 6000):上一次执行完毕时间点之后 6 秒再执行。
- @Scheduled(initialDelay=1000, fixedRate=6000):第一次延迟 1 秒后执行,之后按 fixedRate 的规则每 6 秒执行一次。
方式二:集成Quartz
Quartz的四个概念:
- Job:是一个接口,只定义一个方法 execute(JobExecutionContext context) 在实现接口的execute方法中编写我们需要定时执行的任务
- JobDetall: Job的实现类,描述Job的实现类及其他相关的信息,例如name
- rigger: 是一个类,描述触发Job执行的时间触发规则,有两个子类 :
Simpletrigger :当仅仅需要调度一次或者以固定时间间隔周期执行调度,SimpleTrigger是最合适的选择
CronTrigger:可以通过Cron表达式定义各种复杂事件规则的调度方案
- Scheduler: 调度器就相当于一个容器,装载着任务和触发器,Trigger和JobDetall都可以注册到Scheduler中
第一步:定义两个Job:
CronSchedule可以设置更灵活的方式,定时设置与SpringBoot自带的表达式相同.
同理,先定义两个个Job,与ScheduledJob相同,不过实现Job接口,如下:
package com.example.demo;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @introduce: 定时任务job1
* @outhor: 赫于富
* @DATE: 2020/9/25
**/
public class ScheduledJob implements Job {
private String name;
public void setName(String name){
this.name=name;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat=new SimpleDateFormat("HH:mm:ss");
System.out.println("CRON--->schedule job1 is running ...+" +name+"---->"+ dateFormat.format(new Date()));
}
}
package com.example.demo;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @introduce: 定时任务job1
* @outhor: 赫于富
* @DATE: 2020/9/25
**/
public class ScheduledJob2 implements Job {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
System.out.println("CRON ----> schedule job2 is running ... + " + name + " ----> " + dateFormat.format(new Date()));
}
}
第二步:构建Schedule来执行任务:
package com.example.demo;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;
/**
* @introduce: 定义Scheduler
* @outhor: 赫于富
* @DATE: 2020/9/25
**/
@Component
@PropertySource("classpath:cron.properties")
public class CronSchedulerJob {
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
public void scheduleJob1(Scheduler scheduler) throws SchedulerException{
JobDetail jobDetail= JobBuilder.newJob(ScheduledJob.class) .withIdentity("job1","group1").build();
//6的倍数秒执行,也就是 6 12 18 24
CronScheduleBuilder scheduleBuilder=CronScheduleBuilder.cronSchedule("0/6 * * * * ?");
CronTrigger cronTrigger =TriggerBuilder.newTrigger().withIdentity("trigger1","group1")
.usingJobData("name","赫于富1").withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail,cronTrigger);
}
public void scheduleJob2(Scheduler scheduler) throws SchedulerException{
JobDetail jobDetail=JobBuilder.newJob(ScheduledJob.class) .withIdentity("job2","group2").build();
// 12秒的倍数执行 12 24 36 48 60
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/12 * * * * ?");
CronTrigger cronTrigger=TriggerBuilder.newTrigger().withIdentity("trigger2","group2")
.usingJobData("name","赫于富2").withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail,cronTrigger);
}
//启动定时器
public void scheduleJobs() throws SchedulerException{
Scheduler scheduler=schedulerFactoryBean.getScheduler();
scheduleJob1(scheduler);
scheduleJob2(scheduler);
}
}
第三步:触发定时任务--项目启动时执行:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* @introduce: 项目启动的时候启动定时器
* @outhor: 赫于富
* @DATE: 2020/9/25
**/
@Component
public class MyStartupRunner implements CommandLineRunner {
@Autowired
public CronSchedulerJob schedulerJobs;
@Override
public void run(String... args) throws Exception {
schedulerJobs.scheduleJobs();
System.out.println("定时任务开始执行");
}
}
执行结果: