<一>、先引入依賴:
未采用spring-boot-starter-quartz,直接采用quartz依賴
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version> <!-- 2.2.2-->
</dependency>
<二>、再看spring提供的五個類:
1:JobDetailFactoryBean --需關聯一個Job實現類
2:MethodInvokingJobDetailFactoryBean --無需關聯Job實現類,直接關聯一個自定義對象和需調度的方法即可調度
3:SimpleTriggerFactoryBean --一個簡單的觸發器,可設置間隔、次數等
4:CronTriggerFactoryBean --一個復雜觸發器,可設置各種時間、間隔、次數等配置
5:SchedulerFactoryBean --一個調度bean,可長存于spring容器內,@Autowired后在需要的地方可動態進行任務調度
重點:適用場景,以上1-4只適用于spring容器啟動時進行任務調度,即調度都是提前設置好的、固定的調度參數,并不適用于動態場景,比如用戶在執行了某個操作后,再進行任務調度設置
代碼示例:
1):以下是@Configuration注解的類
@Autowired
private JobFactory jobFactory;
/**
* spring容器啟動就創建一個quartz調度器,其它地方通過這個bean根據業務生成觸發器和任務
* @return quartz調度器
*/
@Bean
public SchedulerFactoryBean createSchedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setApplicationContextSchedulerContextKey(GlobalVariable.APPLICATION_CONTEXT_KEY);
schedulerFactoryBean.setStartupDelay(GlobalVariable.QUARTZ_NOTIFICATION_START_DELAY);
schedulerFactoryBean.setAutoStartup(GlobalVariable.QUARTZ_AUTO_START);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(GlobalVariable.QUARTZ_WAIT_FOR_JOBS_TO_COMPLETE_ON_SHUTDOWN);
schedulerFactoryBean.setJobFactory(jobFactory);
schedulerFactoryBean.setTriggers(cronTriggerFactoryBean.getObject());
return schedulerFactoryBean;
}
/**
* 創建一個訂單過期的job
*
* 這種的只適合spring初始化容器的時候固定執行任務
*
* @return 創建一個job
*/
@Bean
public JobDetailFactoryBean createBookingExpiredJob() {
JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
jobDetailFactoryBean.setGroup(GlobalVariable.QUARTZ_NOTIFICATION_JOB_GROUP_NAME);
jobDetailFactoryBean.setName(GlobalVariable.QUARTZ_NOTIFICATION_BOOKING_EXPIRED_JOB_NAME);
jobDetailFactoryBean.setJobClass(JobTest.class);
Map<String, Object> dataAsMap = new HashMap<>();
dataAsMap.put("booking","123");
jobDetailFactoryBean.setJobDataAsMap(dataAsMap);
return jobDetailFactoryBean;
}
/**
* 創建一個訂單過期的trigger
*
* 這種的只適合spring初始化容器的時候固定執行任務
*
* @return 創建一個trigger
*/
@Bean
public CronTriggerFactoryBean createBookingExpiredTrigger(JobDetailFactoryBean jobDetailFactoryBean) {
CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
cronTriggerFactoryBean.setGroup(GlobalVariable.QUARTZ_NOTIFICATION_JOB_GROUP_NAME);
cronTriggerFactoryBean.setName(GlobalVariable.QUARTZ_NOTIFICATION_BOOKING_EXPIRED_TRIGGER);
String cronExpression = "5/3 * * * * ? *";
cronTriggerFactoryBean.setCronExpression(cronExpression);
cronTriggerFactoryBean.setTimeZone(TimeZone.getDefault());
cronTriggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
return cronTriggerFactoryBean;
}
/**
* 這種的直接把方法作為job,不需要實現job接口
*/
public MethoInvokingJobDetailFactoryBean createMethodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
methodInvokingJobDetailFactoryBean.setTargetClass(null);
methodInvokingJobDetailFactoryBean.setTargetMethod("doJob");
methodInvokingJobDetailFactoryBean.setConcurrent(false);
methodInvokingJobDetailFactoryBean.setGroup("notification");
methodInvokingJobDetailFactoryBean.setName("notification-booking-expired");
return methodInvokingJobDetailFactoryBean;
}
private String getCronExpression(Date startDate) {
Calendar calendar = DateUtils.toCalendar(startDate);
StringBuffer stringBuffer = new StringBuffer(calendar.get(Calendar.SECOND)+"");
stringBuffer.append(" ");
stringBuffer.append(calendar.get(Calendar.MINUTE) + "");
stringBuffer.append(" ");
stringBuffer.append(calendar.get(Calendar.HOUR_OF_DAY) + "");
stringBuffer.append(" ");
stringBuffer.append(calendar.get(Calendar.DAY_OF_MONTH) + "");
stringBuffer.append(" ");
stringBuffer.append(calendar.get(Calendar.MONTH)+1 + "");
stringBuffer.append(" ");
stringBuffer.append("?");
stringBuffer.append(" ");
stringBuffer.append(calendar.get(Calendar.YEAR) + "");
return stringBuffer.toString();
}
2): 具體執行的job,簡單示例:
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class JobTest implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
System.out.println("test----test");
}
}
3):這是自定義的JobFactory,這個類用于解決:上面JobTest里面如果有Autowired的spring容器bean,在execute方法里面調用時注入為null的問題
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
以上在spring容器啟動時候,就會從第5秒開始每3秒運行一次、運行結果
以上是spring容器啟動后,進行任務固定調度配置的運行,但是業務中一般都是動態創建job和trigger
華麗的分割線
<三>:以下是動態創建job和trigger:
代碼示例:
1):@Configuration注解的類里面
@Autowired
private JobFactory jobFactory;
/**
* spring容器啟動就創建一個quartz調度器,其它地方通過這個bean根據業務生成觸發器和任務
* @return quartz調度器
*/
@Bean
public SchedulerFactoryBean createSchedulerFactoryBean(){
SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
schedulerFactoryBean.setApplicationContextSchedulerContextKey(GlobalVariable.APPLICATION_CONTEXT_KEY);
schedulerFactoryBean.setStartupDelay(GlobalVariable.QUARTZ_NOTIFICATION_START_DELAY);
schedulerFactoryBean.setAutoStartup(GlobalVariable.QUARTZ_AUTO_START);
schedulerFactoryBean.setWaitForJobsToCompleteOnShutdown(GlobalVariable.QUARTZ_WAIT_FOR_JOBS_TO_COMPLETE_ON_SHUTDOWN);
schedulerFactoryBean.setJobFactory(jobFactory);
return schedulerFactoryBean;
}
2): 具體執行的job,簡單示例
public class NotificationJobService implements Job {
private static final Logger LOGGER = LoggerFactory.getLogger(NotificationJobService.class);
@Autowired
private IMOpenfireServer imOpenfireServer;
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOGGER.info("whether booking request has expired!");
JobDetail jobDetail = context.getJobDetail();
JobDataMap jobDataMap = jobDetail.getJobDataMap();
Booking booking = (Booking) jobDataMap.get("booking");
}
}
3):這是自定義的JobFactory,這個類用于解決:上面
NotificationJobService 里面如果有Autowired的spring容器bean,在execute方法里面調用時注入為null的問題
import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;
import org.springframework.stereotype.Component;
@Component
public class JobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory capableBeanFactory;
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object jobInstance = super.createJobInstance(bundle);
capableBeanFactory.autowireBean(jobInstance);
return jobInstance;
}
}
4): 動態設置觸發器和任務,比如調用下面的startJob方法,就開始進行觸發器和任務配置并進行調度、代碼示例:
@Autowired
private SchedulerFactoryBean schedulerFactoryBean;
public void startJob(Date startDate,Booking booking) {
JobDataMap jobDataMap = new JobDataMap();
jobDataMap.put("booking",booking);
//創建一個job
JobDetail jobDetail = JobBuilder.newJob(NotificationJobService.class).setJobData(jobDataMap).build();
//創建一個trigger
Trigger trigger = TriggerBuilder.newTrigger().startAt(startDate).forJob(jobDetail).build();
try {
schedulerFactoryBean.getScheduler().scheduleJob(jobDetail,trigger);
} catch (SchedulerException e) {
LOGGER.error("schedule NotificationJob failed! {}",e);
}
}
以上就是動態設置調度任務的過程。
完!
posted on 2017-12-27 18:18
朔望魔刃 閱讀(2026)
評論(0) 編輯 收藏 所屬分類:
java