一、定时任务
启动类中添加注解@EnableScheduling表示开启定时任务
package com.lj.code;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling //开启定时任务
public class Quartz01Application {
public static void main(String[] args) {
SpringApplication.run(Quartz01Application.class, args);
}
}
建立任务类,
注解@Scheduled(fixedRate = 1000)表示每隔1秒执行一次
package com.lj.code;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/*
人物类
*/
@Component //成为组件,让spring管理
@Slf4j
public class Task {
// @Scheduled(fixedRate=5000):上⼀次开始执⾏时间点之后5秒再执⾏
// @Scheduled(fixedDelay=5000):上⼀次执⾏完毕时间点之后5秒再执⾏
// @Scheduled(initialDelay=1000, fixedRate=5000):第⼀次延迟1秒后执⾏,之后按fixedRate的规则每5秒执⾏⼀次
// @Scheduled(cron="*/5 * * * * *"):通过cron表达式定义规则
@Scheduled(cron = "10 10 * * * ?")
public void test(){
log.warn("现在时间:" + LocalDateTime.now());
}
}
Scheduled 参数
@Scheduled(fixedRate=5000): 上⼀次开始执⾏时间点之后 5 秒再执⾏
@Scheduled(fixedDelay=5000): 上⼀次执⾏完毕时间点之后 5 秒再执⾏
@Scheduled(initialDelay=1000, fixedRate=5000): 第⼀次延迟 1 秒后执⾏ , 之后按 fixedRate 的规则
每 5 秒执⾏⼀次
@Scheduled(cron="*/5 * * * * *"): 通过 cron 表达式定义规则
需要导入日志依赖
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
测试类使用死循环 ,否则只能执行一次
结果
cron 表达式
cron 表达式是一个字符串 , 以 5 或者 6 个空格隔开 ( 示例中是被 5 个空格隔开 ), 字符串被切割为 6 个或者 7 个域 , 每个域都代表不同的含义
{Seconds} {Minutes} {Hours} {DayofMonth} {Month} {DayofWeek} {Year}
{Seconds} {Minutes} {Hours} {DayofMonth} {Month} {DayofWeek}
范围
每个域都可以用数字表示,还可以出现如下特殊字符
注意:日和星期不能同时出现
cron表达式的缺点
1.任务在内存中执行,一旦系统断开,任务就消失了,任务数据也就没有了
2.不能实现共享,存在于本机内存中
二、Quartz创建定时任务
任务存储方式有两种
内存方式 (RAMJobStore) :将任务临时存储到内存中,仅支持单项目部署,项目重启后任务会失效,不支持由调度器控制任务漂移,不建议使用。
数据库方式 (JDBCJobStore) : Quartz 提供了多种数据库的所需表结构脚本,它内部通过 DataSource 来 操作数据,支持分布式方式部署、支持任务漂移,项目重启后任务不会丢失,直到任务执行完成后才会 被从数据库内清除。
内存方式步骤:
1.实例化SchedulerFactory 调度器工厂
SchedulerFactory SchedulerFactory=new StdSchedulerFactory();
StdSchedulerFactory可读取配置文件
2.得到Scheduler 调度器
Scheduler scheduler = SchedulerFactory.getScheduler();
Scheduler 维护了一个 JobDetails(任务) 和 Triggers(触发时间) 的注册表。
3.创建一个任务类(myJob)并实现job接口并定义任务
package com.lj.code;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
@Slf4j
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
Object name = jobExecutionContext.getJobDetail().getJobDataMap().get("name");
log.warn(name + "正在努力的搞卫生………………");
}
}
4.测试类中创建任务(myJob中定义的)
5.创建触发器
//4.创建触发器 Trigger trigger = TriggerBuilder.newTrigger() .withDescription("大扫除触发器") .withIdentity("大扫除", "厕所") .startAt(new Date())//开始时间 //简单触发器 // .withPriority(10)//调度器的优先级 默认为5 // .withSchedule( // simpleSchedule()//调度规则 // .withIntervalInSeconds(10) //间隔时间10s Seconds // .withRepeatCount(10) //SimpleTrigger.REPEAT_INDEFINITELY 一直运行 // ) .withSchedule( CronScheduleBuilder.cronSchedule("* * * * * ?") ) .build();
6.将触发器绑定到调度器上面去
scheduler.scheduleJob(jobDetail,trigger);
7.启动调度器
scheduler.start();
整体代码:
package com.lj.code;
import org.junit.jupiter.api.Test;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
@SpringBootTest
class Quartz01ApplicationTests {
@Test
void contextLoads() throws Exception{
//1.实例化调度器工厂
SchedulerFactory schedulerFactory = new StdSchedulerFactory();
//2.得到调度器
Scheduler scheduler = schedulerFactory.getScheduler();
//3.创建任务
//job 模板 JobDetail 实例
JobDetail jobDetail = newJob(MyJob.class)
.withDescription("开年大扫除")
.withIdentity("大扫除", "厕所") //name 名字 group 分组 任务id =大扫除+厕所
.usingJobData("name", "王阿姨")
.build(); //构建
// JobDataMap jobDataMap = jobDetail.getJobDataMap();
// jobDataMap.put("dada","dadada");
JobDetail jobDetail2 = newJob(MyJob.class)
.withDescription("开年大扫除")
.withIdentity("大扫除", "厕所") //name 名字 group 分组 任务id =大扫除+厕所
.usingJobData("name", "李阿姨")
.build(); //构建
//4.创建触发器
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("大扫除触发器")
.withIdentity("大扫除", "厕所")
.startAt(new Date())//开始时间
//简单触发器
// .withPriority(10)//调度器的优先级 默认为5
// .withSchedule(
// simpleSchedule()//调度规则
// .withIntervalInSeconds(10) //间隔时间10s Seconds
// .withRepeatCount(10) //SimpleTrigger.REPEAT_INDEFINITELY 一直运行
// )
.withSchedule(
CronScheduleBuilder.cronSchedule("* * * * * ?")
)
.build();
//5.将触发器和任务绑定到调度器
scheduler.scheduleJob(jobDetail,trigger);
//6.启动调度器
scheduler.start();
}
}
8.启动后控制台结果
job和jobDetail的区别
job是任务模板,jobDetail是实例
现在创建两个jobDetail实例 ,usingJobData不同
在任务模板中获取到name属性
package com.lj.code; import lombok.extern.slf4j.Slf4j; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @Slf4j public class MyJob implements Job { @Override public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { Object name = jobExecutionContext.getJobDetail().getJobDataMap().get("name"); log.warn(name + "正在努力的搞卫生………………"); } }
运行结果
如果想要放入很多数据,可以用JobDataMap集合
设置时间以及执行次数
SimpleTrigger 包含几个特点:开始时间、结束时间、重复次数以及重复执行的时间间隔。
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("大扫除触发器")
.withIdentity("大扫除", "厕所")
.startAt(new Date())//开始时间
.withSchedule(
simpleSchedule()
.withIntervalInSeconds(1)//时间间隔
.withRepeatCount(SimpleTrigger.REPEAT_INDEFINITELY) //SimpleTrigger.REPEAT_INDEFINITELY
)
.build();
基于 Cron 表达式的触发器 CronTrigger
Trigger trigger = TriggerBuilder.newTrigger()
.withDescription("大扫除触发器")
.withIdentity("大扫除", "厕所")
.startAt(new Date())//开始时间
.withSchedule(
CronScheduleBuilder.cronSchedule("* * * * * ?")
)
.build();
结果