一、项目pom引入Quartz依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
二、定时任务
定时任务分为两种,一种是简单的通过配置文件设定,另一种是通过程序动态对定时任务进行增删改查。
(一)通过配置文件设定定时任务
1.创建任务类
public class QuartzDemo implements Job,Serializable {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
System.out.println("quartz runing ..."+map.get("key"));
}
}
public class QuartzDemo2 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
System.out.println("quartz2 runing ...");
}
}
(二)创建Quartz配置文件
这里可以一起配置多个定时任务
@Configuration
public class QuartzConfig {
@Bean
public JobDetail myJobDetail(){
JobDetail jobDetail = JobBuilder.newJob(QuartzDemo2.class)
.withIdentity("myJob1","myJobGroup1")
//JobDataMap可以给任务execute传递参数
.usingJobData("key","job_param1")
.storeDurably()
.build();
return jobDetail;
}
@Bean
public Trigger myTrigger(JobDetail myJobDetail){
Trigger trigger = TriggerBuilder.newTrigger()
.forJob(myJobDetail)
.withIdentity("myTrigger1","myTriggerGroup1")
.usingJobData("key","job_trigger_param1")
.startNow()
//.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
return trigger;
}
//配置多个定时器
@Bean
public JobDetail myJobDetail2(){
JobDetail jobDetail = JobBuilder.newJob(QuartzDemo.class)
.withIdentity("myJob2","myJobGroup2")
//JobDataMap可以给任务execute传递参数
.usingJobData("key","job_param1")
.storeDurably()
.build();
return jobDetail;
}
@Bean
public Trigger myTrigger2(JobDetail myJobDetail2){
Trigger trigger = TriggerBuilder.newTrigger()
.forJob(myJobDetail2)
.withIdentity("myTrigger2","myTriggerGroup2")
.usingJobData("key","job_trigger_param1")
.startNow()
//.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(5).repeatForever())
.withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
.build();
return trigger;
}
}
(三)Application,main加入@EnableScheduling注解来使系统自动执行定时器
@SpringBootApplication
//使能异步方法
@EnableAsync
//使能定时器,系统自动执行定时器
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
这样在项目启动的时候,就可以直接启动了,控制台输出如下:
(二)通过Scheduler、JobDetail、Trigger动态创建定时任务
1.创建定时任务类
public class QuartzDemo implements Job,Serializable {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
JobDataMap map = jobExecutionContext.getJobDetail().getJobDataMap();
System.out.println("quartz runing ..."+map.get("key"));
}
}
2.创建定时任务工具类,这里需要注意的是,为了接下来使用Quartz的持久化功能,Scheduler不能使用StdSchedulerFactory.getDefaultScheduler()产生,必须由系统默认的Scheduler来注入,由于在Controller层也需要调用工具类,所以工具类加上@Component交由spring容器管理。
package com.itheima.testQuartz;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
@Component
public class QuartzManager {
private final String JOB_GROUP_NAME = "JOB_GROUP_NAME";
private final String TRIGGER_GROUP_NAME = "TRIGGER_GROUP_NAME";
@Autowired
private Scheduler scheduler;
/**
* 添加定时任务
*/
public void addJob(String jobName,String jobGroupName,String triggerName,String triggerGroupName,Class cls,String time){
try {
JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroupName).build();
JobDataMap map = jobDetail.getJobDataMap();
map.put("key", "test");
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(CronScheduleBuilder.cronSchedule(time)).build();
scheduler.scheduleJob(jobDetail,trigger);
scheduler.start();
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public void addJob(String jobName,String triggerName,String groupName,Class cls,String time){
addJob(jobName,groupName,triggerName,groupName,cls,time);
}
public void addJob(String jobName,String triggerName,Class cls,String time){
addJob(jobName,JOB_GROUP_NAME,triggerName,TRIGGER_GROUP_NAME,cls,time);
}
/**
* 删除定时任务
*/
public boolean deleteJob(String jobName,String groupName){
boolean result = false;
try {
JobKey jobKey = new JobKey(jobName,groupName);
if(scheduler.checkExists(jobKey)){
result = scheduler.deleteJob(jobKey);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
return result;
}
public void deleteJob(String jobName){
deleteJob(jobName,JOB_GROUP_NAME);
}
/**
* 停止任务
*/
public void pauseJob(String jobName,String groupName){
try {
JobKey jobKey = new JobKey(jobName,groupName);
if(scheduler.checkExists(jobKey)){
scheduler.pauseJob(jobKey);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public void pauseJob(String jobName){
pauseJob(jobName,JOB_GROUP_NAME);
}
/**
* 再次启动Job
* @param jobName
* @param groupName
*/
public void resumeJob(String jobName,String groupName){
try {
JobKey jobKey = new JobKey(jobName,groupName);
if(scheduler.checkExists(jobKey)){
scheduler.resumeJob(jobKey);
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public void resumeJob(String jobName){
resumeJob(jobName,JOB_GROUP_NAME);
}
}
3.Controller层进行测试
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private QuartzManager quartzManager;
@RequestMapping("/addQuartz")
@ResponseBody
public String addQuartz() throws MessagingException {
quartzManager.addJob("job1","trigger1",QuartzDemo.class,"0/5 * * * * ?");
return "addQuartz yes";
}
@RequestMapping("/delQuartz")
@ResponseBody
public String delQuartz() throws MessagingException {
quartzManager.deleteJob("job1");
return "delQuartz yes";
}
}
通过访问"/addQuartz"和"/delQuartz",就可以动态开启和关闭定时任务了。
三、Quartz的持久化问题
1.需要按照上述内容创建工具类QuartzManager
2.配置Application.yml文件,设置Quartz持久化由默认的RAM内存改为JDBC数据库,需要配置数据库连接
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/shiro
username: root
password: szd117szd
quartz:
job-store-type: jdbc
jdbc:
initialize-schema: always
3.在对应的mysql数据库创建对应的表格
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
JOB_NAME VARCHAR(200) NOT NULL,
JOB_GROUP VARCHAR(200) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(200) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(200) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(200) NULL,
JOB_GROUP VARCHAR(200) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(200) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;
4.测试
通过打开定时任务,然后重启服务器,之前的定时任务就会直接继续运行,同时通过工具类对定时任务的增删改查也会直接修改到数据库。