@
前言
在很多剛使用quartz的小伙伴的體驗中,如果說沒有碰到這個問題的話,那可能就是還沒有往深入的走,也或許有其他的解決方案。
然后wangwang我呢,也找了很久的資料才找到的。然后跟自己的項目需求相結合就成了這個亞子。
后面會放參考博客內容的:(本次為簡單參考為主,不做過多講解)
一、先圖解一下本次文件內容
二、放代碼....
MyJobFactory.java
package com.bj.quartz.config;
import groovy.util.logging.Slf4j;
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MyJobFactory extends SpringBeanJobFactory
implements ApplicationContextAware {
@Autowired
private transient AutowireCapableBeanFactory beanFactory;
@Override
public void setApplicationContext(final ApplicationContext context) {
beanFactory = context.getAutowireCapableBeanFactory();
}
@Override
protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
final Object job = super.createJobInstance(bundle);
beanFactory.autowireBean(job);
return job;
}
}
QuartzConfiguration.java
package com.bj.quartz.config;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.io.IOException;
import java.util.Properties;
@Configuration
public class QuartzConfiguration {
@Autowired
private MyJobFactory myJobFactory;
//創建調度器工廠
@Bean(name = "SchedulerFactory")
public SchedulerFactoryBean schedulerFactoryBean(){
SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
factoryBean.setJobFactory(myJobFactory);
return factoryBean;
}
@Bean(name="scheduler")
public Scheduler scheduler(){
return schedulerFactoryBean().getScheduler();
}
}
配置完這些之后,其實就可以了,你就可以通過控制scheduler去生成jobDetail,trigger之類的。並且不用擔心spring管理的容器無法注入進來的問題
可能有些人說,這么就這么一點點呢,當然咯quartz的內容往往不止這一些,還有一些持久化的策略之類的,甚至可以提供搭建一個定時任務的控制平台。只不過暫時我這個就只有這些,能開機就使用的定時任務。
接下來的就是我本次需求的兩個重點測試:1、定時任務自動停止,2、定時任務中參數改變策略
不需要的小伙伴也可以不看。。。。
三、測試代碼
0、創建定時任務
initQuartz.java
這個是寫的一個自啟動的時候就編譯一個定時任務規則的類
package com.bj.quartz.init;
import com.bj.quartz.service.TScheduleTriggerParamService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class initQuartz implements ApplicationRunner {
//job1的定時任務
@Value("${jobName1}")
private String jobName;
@Value("${groupName1}")
private String groupName;
@Value("${cron1}")
private String cron;
//job2的定時任務
@Value("${jobName2}")
private String jobName2;
@Value("${groupName2}")
private String groupName2;
@Value("${cron2}")
private String cron2;
@Autowired
private Scheduler scheduler;
private static final Logger logger = LoggerFactory.getLogger(initQuartz.class);
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
logger.info("================quartz啟動成功==============");
//創建job1
addQuartz(jobName,groupName,cron);
//創建job2
addQuartz(jobName2,groupName2,cron2);
}
public void addQuartz(String jobName, String jobGroup, String cron){
try {
//JobName+JobGroup=Primary Key
//根據jobName和jobGroup生成TriggerKey
TriggerKey triggerKey =
TriggerKey.triggerKey(jobName, jobGroup);
//根據TriggerKey到Scheduler調度器中獲取觸發器
CronTrigger cronTrigger = (CronTrigger)
scheduler.getTrigger(triggerKey);
System.out.println("創建調度器");
//創建任務詳情
JobDetail jobDetail=
JobBuilder.newJob((Class<? extends Job>) Class.forName(jobName))
.withIdentity(jobName,jobGroup)
.build();
//往Job任務中傳遞參數
JobDataMap jobDataMap = jobDetail.getJobDataMap();
//創建表達式調度器
CronScheduleBuilder cronSchedule =
CronScheduleBuilder.cronSchedule(cron);
//創建Trigger
cronTrigger= TriggerBuilder.newTrigger()
.withIdentity(jobName, jobGroup)
.withSchedule(cronSchedule)
.build();
//將jobDetail和Trigger注入到scheduler調度器中
scheduler.scheduleJob(jobDetail,cronTrigger);
}catch (Exception e){
e.printStackTrace();
}
}
}
1、定時任務自動停止
任務類
Myjob1.java
package com.bj.quartz.job;
import com.bj.util.ControllerUtil;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class Myjob1 implements Job {
@Value("${jobName1}")
private String jobName;
@Value("${groupName1}")
private String groupName;
@Value("${cron1}")
private String cron;
@Autowired
private Scheduler scheduler;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
//任務主體
taskBody(jobExecutionContext);
}
/**
* 任務主體
*/
private void taskBody(JobExecutionContext jobExecutionContext){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//獲取任務詳情中的dataMap集合
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
System.out.println("這是我的myjob1111111定時任務"+sdf.format(new Date()));
System.out.println("本方法的一個參數有:"+jobDataMap.size());
System.out.println("job:"+jobDataMap.get("job")+"level"+jobDataMap.get("level"));
System.out.println("-------------------------------");
String BockStartTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
long timeSize=0;
try {
/*
* 拿當前時間和規定時間相比較
* */
timeSize = this.compareTime2(BockStartTime, "20200402172430");
} catch (ParseException e) {
e.printStackTrace();
}
/*
* 如果大於0則代表任務該停下來
* */
if(timeSize>0){
System.err.println("stop job 任務!!!");
//調用停止定時任務的方法
this.stopQuary(jobName,groupName);
}
}
/**
* 關閉quary定時任務
*/
private void stopQuary(String jobName, String groupName){
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
try {
/*
*停止觸發器
* */
scheduler.pauseTrigger(triggerKey);
/*
*移除觸發器
* */
scheduler.unscheduleJob(triggerKey);
scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
} catch (SchedulerException e) {
e.printStackTrace();
}
}
/**
* TODO 取兩個時間的差
* @param day1
* @param day2
* @return 秒
* @throws ParseException
*/
public long compareTime2(String day1, String day2)
throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
Date rjsj = df.parse(day1);
Date dksj = df.parse(day2);
long stateTimeLong = rjsj.getTime();
long endTimeLong = dksj.getTime();
long day = (stateTimeLong - endTimeLong) / 1000L;
return day;
}
}
2、定時任務中參數改變策略
Myjob2.java
package com.bj.quartz.job;
import com.bj.entity.TScheduleTriggerParam;
import com.bj.quartz.service.TScheduleTriggerParamService;
import com.bj.quartz.util.paramMap;
import groovy.util.logging.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@Component
@Slf4j
public class Myjob2 implements Job {
@Autowired
private TScheduleTriggerParamService tScheduleTriggerParamService;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
//任務主體
taskBody(jobExecutionContext);
}
private void taskBody(JobExecutionContext jobExecutionContext){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//獲取任務詳情中的dataMap集合
JobDetail jobDetail = jobExecutionContext.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
//更新params里面的值
List<TScheduleTriggerParam> params =
tScheduleTriggerParamService.queryScheduleParamLst(1);
for (TScheduleTriggerParam param : params) {
jobDataMap.put(param.getName(),param.getValue());
}
System.err.println("這是我的myjob定時任務"+sdf.format(new Date()));
System.err.println("本方法的一個參數有:"+jobDataMap.size());
System.err.println("name:"+jobDataMap.get("name")+"score"+jobDataMap.get("score"));
System.out.println("-------------------------------");
//我自己提供的一個Map值
HashMap jobMap1 = paramMap.getJobMap1();
System.out.println("自己建的map:"+jobMap1.get("hh"));
}
}
這個我就得嘮嘮嗑了,參數的設置可能有三種方式:
1、使用一個靜態常量的map類,然后每次調用修改參數的service的時候同時把map類中的數據重新替換掉,
2、使用redis進行存儲,如果是多集群的話,
3、每次使用job任務的時候都到數據庫去查詢一下參數並且更替掉。
根據自身情況來吧。。
后言
不過說實話,如果是需要深入了解的還是得看看官方文檔之類的。
像w3c中的quartz。
還有我看到的比較詳細的:觸發器介紹
本次參考后解決問題的博客:Springboot整合quartz框架(附代碼)
我是wangwang,感謝能看到這里。
歡迎在評論區進行評論。