spring boot 集成 quartz
spring boot 自带的定时任务 schedule使用起来非常简单,但是不灵活。如果需要动态的去修改任务间隔,可以实现,但就是比较麻烦。这里记录一下quartz在spring boot 中的使用,权当抛砖引玉。
1、引入jar包
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
2、新建一个任务类,实现Job接口
@DisallowConcurrentExecution
@Component
public class OneJob implements Job{
private String name;
private int pid;
private Logger logger = LoggerFactory.getLogger(OneJob .class);
public void doSomething(){
logger.info(new Date()+"--"+name+" :启动任务");
try {
Thread.sleep(7000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.info(pid+"任务结束");
}
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
crawling();
}
public void setName(String name) {
this.name = name;
}
public void setPid(int pid) {
this.pid = pid;
}
}
注解@DisallowConcurrentExecution表示一次只允许执行一个任务,不加这个注解的话,可以多任务同时运行
注意:任务类中属性比如name,pid 和其他对象类,不能通过spring boot自动注入的方式获取,如果通过@Autowired方式注入属性值,会是null值,如何注入,下一步会讲。
3、quartz任务操作类
上一步提到的如何注入job类参数,需要通过JobDetail.getJobDataMap()方法注入。
@Service
public class QuartzService {
private static Scheduler scheduler=getScheduler();
private static String JOB_GROUP_NAME = "OJ_JOBGROUP_NAME";
private static String TRIGGER_GROUP_NAME = "OJ_TRIGGERGROUP_NAME";
private static Map<String,TriggerKey> TRIGGERKEYMAP = new HashMap<>();
private static Map<String,JobKey> JOBKEYMAP = new HashMap<>();
@Value("${task.pid}")
private int pid;
/**
* 创建一个调度对象
* @return
* @throws SchedulerException
*/
private static Scheduler getScheduler() {
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler=null;
try {
scheduler = sf.getScheduler();
} catch (SchedulerException e) {
e.printStackTrace();
}
return scheduler;
}
/**
* 添加一个任务
* @param jobName
* @param task
* @param cron
* @return
*/
public Map<String,String> addJob(String jobName,Class task,String cron){
Map<String,String> map = new HashMap<>();
try {
Trigger trigger = newTrigger()
.withIdentity(jobName,TRIGGER_GROUP_NAME)
.startNow()
.withSchedule(cronSchedule(cron))
.build();
TRIGGERKEYMAP.put(jobName,trigger.getKey());
JobDetail jobDetail = newJob()
.ofType(task)
.withIdentity(jobName,JOB_GROUP_NAME)
.build();
JOBKEYMAP.put(jobName,jobDetail.getKey());
jobDetail.getJobDataMap().put("name",jobName);
jobDetail.getJobDataMap().put("pid",pid);
try {
Date date = scheduler.scheduleJob(jobDetail,trigger);
}catch (ObjectAlreadyExistsException e){
map.put("info","Job already exists");
map.put("status","0");
return map;
}
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (SchedulerException e) {
throw new RuntimeException(e);
}
map.put("info","start job success");
map.put("status","1");
return map;
}
/**
* 修改触发器时间间隔
* @param jobName
* @param cron
* @throws SchedulerException
*/
public Map<String,String> modifyJobTime(String jobName, String cron){
System.out.println("modifyJobTime");
Trigger trigger = newTrigger()
.withIdentity(jobName,TRIGGER_GROUP_NAME)
.startNow()
.withSchedule(cronSchedule(cron))
.build();
Map<String,String> map = new HashMap<>();
try {
scheduler.rescheduleJob(trigger.getKey(),trigger);
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","modify failed");
map.put("status","0");
return map;
}
map.put("info","success");
map.put("status","1");
return map;
}
/**
* * @param jobName
* 停止使用相关的触发器
*/
public Map<String,String> pauseTrigger(String jobName) {
System.out.println("pause trigger");
Map<String,String> map = new HashMap<>();
try {
scheduler.pauseTrigger(TRIGGERKEYMAP.get(jobName));
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","pause failed");
map.put("status","0");
return map;
}
map.put("info","success");
map.put("status","1");
return map;
}
/**
* 恢复使用相关的触发器
* @param jobName
*/
public Map<String,String> resumeTrigger(String jobName) {
System.out.println("resume trigger");
Map<String,String> map = new HashMap<>();
try {
scheduler.resumeTrigger(TRIGGERKEYMAP.get(jobName));
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","resume trigger failed");
map.put("status","0");
return map;
}
map.put("info","success");
map.put("status","1");
return map;
}
/**
* 暂停任务
* @param jobName
*/
public Map<String,String> pauseJob(String jobName){
System.out.println("pause job");
Map<String,String> map = new HashMap<>();
try {
scheduler.pauseJob(JOBKEYMAP.get(jobName));
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","pause job failed");
map.put("status","1");
return map;
}
map.put("info","success");
map.put("status","2");
return map;
}
/**
* 恢复任务
* @param jobName
*/
public Map<String,String> resumeJob(String jobName) {
System.out.println("resume job");
Map<String,String> map = new HashMap<>();
try {
scheduler.resumeJob(JOBKEYMAP.get(jobName));
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","resume job failed");
map.put("status","2");
return map;
}
map.put("info","success");
map.put("status","1");
return map;
}
/**
* 删除任务
* @param jobName
*/
public Map<String,String> deleteJob(String jobName) {
System.out.println("deleteJob");
Map<String,String> map = new HashMap<>();
try {
scheduler.deleteJob(JOBKEYMAP.get(jobName));
} catch (SchedulerException e) {
e.printStackTrace();
map.put("info","delete job failed");
map.put("status","0");
return map;
}
map.put("info","success");
map.put("status","1");
return map;
}
/**
* 判断是否还有在执行任务
* @return
*/
public boolean hasJobRunning(){
List<JobExecutionContext> list = null;
try {
list = scheduler.getCurrentlyExecutingJobs();
} catch (SchedulerException e) {
e.printStackTrace();
return false;
}
if(list.size()>0) return true;
return false;
}
/**
* 关闭调度器
* @throws SchedulerException
*/
public Boolean shutDownScheduler(){
try {
if (scheduler.isStarted()) {
scheduler.shutdown();
return true;
}
} catch (SchedulerException e) {
e.printStackTrace();
}
return false;
}
}
以上就是基本的一些quartz操作,如果需要其他功能,自行在添加即可。
多个定时任务,新建任务类去实现Job接口。
注意事项:
1、一个触发器可以触发多个任务
2、多个任务按该触发器设定频率运行
3、同一组内不能有同样的任务名或者触发器名
4、触发器暂停,该触发器控制的所有任务暂停
5、如果一个任务运行时长大于任务间隔,则执行完毕该任务会继续执行下个任务,比如:任务运行7s,间隔5s,下一次任务会等待第一次执行完再继续执行
6、更改触发器执行间隔,将等待正在执行的任务执行完毕后,再使用新的执行间隔
7、如果暂停触发器,正在执行的任务会执行完毕
8、如果进行过任务触发间隔动态修改,暂停后再启动,会等到时间一致才会到正确的频率上,原因未知。
如有问题,欢迎留言讨论