<一>、先引入依赖:
未采用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
朔望魔刃 阅读(2021)
评论(0) 编辑 收藏 所属分类:
java