随笔-95  评论-31  文章-10  trackbacks-0
<一>、先引入依赖:
未采用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

只有注册用户登录后才能发表评论。


网站导航: