springboot-quartz普通任务与可传参任务

摘要:
(做了一个测试,测试目的是看通过此类型调度类型是否也能传入参数所以定义了一个带入参的自定义方法即publicvoidwork(JobExecutionContextjobExecutionContext),最中测试结果是springquartz会报找不到work方法及Nosuchmethodwork(),其默认执行我们生命的work无入参的方法。2)可传参任务必须继承QuartzJobBean,重写protectedvoidexecuteInternalthrowsJobExecutionException方法,其中JobExecutionContext就是我们在定义调度器明细时传入参数的上下文,我们可以通过JobExecutionContext取出传入的map,调度任务最终执行的就是executeInternal方法,使用该调度明细任务无法使用自定义方法。--添加springboot对Quartz的支持--˃org.quartz-schedulerquartz2.3.0org.springframeworkspring-context-support˂!

两者区别与作用:
普通任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细自定义执行方法bean(MethodInvokingJobDetailFactoryBean) -->调度bean(我们定义的job类)
可传参任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细bean(JobDetailFactoryBean)
如上是我们在配置调度器时的具体步骤及相互之间的依赖,区别主要在调度明细bean上,普通任务是(MethodInvokingJobDetailFactoryBean),而可传参任务是(JobDetailFactoryBean):
1)普通任务可以自定义执行方法,也就是说在其配置的调度bean(我们定义的job类)中我们可以自定义调度器最终执行的方法,可以叫work1也可以叫work2,and so on。而且要记住的一点,必须是无入参的方法!!!(做了一个测试,测试目的是看通过此类型调度类型是否也能传入参数所以定义了一个带入参的自定义方法即public void work(JobExecutionContext jobExecutionContext),最中测试结果是spring quartz会报找不到work方法及No such method work(),其默认执行我们生命的work无入参的方法。
2)可传参任务必须继承QuartzJobBean,重写protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException方法,其中JobExecutionContext就是我们在定义调度器明细时传入参数的上下文,我们可以通过JobExecutionContext取出传入的map,调度任务最终执行的就是executeInternal方法,使用该调度明细任务无法使用自定义方法。

提供三种形式的定时任务:
1、固定等待时间 @Scheduled(fixedDelay = 时间间隔 )
2、固定间隔时间 @Scheduled(fixedRate = 时间间隔 )
3、Corn表达式 @Scheduled(cron = Corn表达式)

添加依赖(不知道为什么要加jboss-logging依赖,没有会报错)

<!--添加springboot对Quartz的支持 -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        
        <!--https://mvnrepository.com/artifact/org.jboss.logging/jboss-logging -->
        <dependency>
            <groupId>org.jboss.logging</groupId>
            <artifactId>jboss-logging</artifactId>
        </dependency>    
View Code

配置quartz.properties

#===============================================================     
#Configure Main Scheduler Properties     调度器属性
#===============================================================  
#调度器的实例名     
org.quartz.scheduler.instanceName = QuartzScheduler     
#调度器的实例ID,大多数情况设置为auto即可  
org.quartz.scheduler.instanceId = AUTO     
 
#===============================================================     
#Configure ThreadPool     线程池属性
#===============================================================   
#处理Job的线程个数,至少为1,但最多的话最好不要超过100,在多数机器上设置该值超过100的话就会显得相当不实用了,特别是在你的 Job 执行时间较长的情况下
org.quartz.threadPool.threadCount =  5     
#线程的优先级,优先级别高的线程比级别低的线程优先得到执行。最小为1,最大为10,默认为5
org.quartz.threadPool.threadPriority = 5 
#一个实现了 org.quartz.spi.ThreadPool 接口的类,Quartz 自带的线程池实现类是 org.quartz.smpl.SimpleThreadPool      
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool     
 
#===============================================================     
#Configure JobStore 作业存储设置
#===============================================================      
#要使 Job 存储在内存中需通过设置  org.quartz.jobStrore.class 属性为 org.quartz.simpl.RAMJobStore 
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore    
View Code

一、普通任务

1、任务类

packagecloud.app.prod.home.quartz.mem;

importorg.apache.log4j.Logger;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.scheduling.annotation.EnableScheduling;
importorg.springframework.stereotype.Component;

importcloud.app.prod.home.common.FailException;

/*** Author : YongBo Xie </br>
 * File Name: ScheduleTask.java </br>
 * Created Date: 2018年3月31日 下午3:37:43 </br>
 * Modified Date: 2018年3月31日 下午3:37:43 </br>
 * Version: 1.0 </br>
*/@Configuration  
@Component //此注解必加  
@EnableScheduling //此注解必加
public classScheduleTask {
    
    private static Logger logger = Logger.getLogger(ScheduleTask.class);
    
    public void marketingActivity() throwsFailException {
        logger.info("execute activity");
    }

}
View Code

2、Quartz配置类

packagecloud.app.prod.home.quartz.mem;

importorg.quartz.Trigger;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.scheduling.quartz.CronTriggerFactoryBean;
importorg.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
importorg.springframework.scheduling.quartz.SchedulerFactoryBean;

/*** Author : YongBo Xie </br>
 * File Name: QuartzConfigration.java </br>
 * Created Date: 2018年3月31日 下午3:42:04 </br>
 * Modified Date: 2018年3月31日 下午3:42:04 </br>
 * Version: 1.0 </br>
*/@Configuration
public classQuartzConfigration {
        
    /*** Details:配置定时任务 
     */@Bean(name = "marketingActivityJobDetail")  
    public MethodInvokingJobDetailFactoryBean detailFactoryBean(ScheduleTask task) {//ScheduleTask为需要执行的任务  
        MethodInvokingJobDetailFactoryBean jobDetail = newMethodInvokingJobDetailFactoryBean();  
        /**  是否并发执行 
         *  例如每5s执行一次任务,但是当前任务还没有执行完,就已经过了5s了, 
         *  如果此处为true,则下一个任务会执行,如果此处为false,则下一个任务会等待上一个任务执行完后,再开始执行 
         */jobDetail.setConcurrent(false);  
          
        jobDetail.setName("marketing_activity");//设置任务的名字  
        jobDetail.setGroup("marketing_activity");//设置任务的分组,这些属性都可以存储在数据库中,在多任务的时候使用  
        
        /** 为需要执行的实体类对应的对象 
         */jobDetail.setTargetObject(task);  
          
        /** marketingActivity为需要执行的方法 
         * 通过这几个配置,告诉JobDetailFactoryBean我们需要执行定时执行ScheduleTask类中的marketingActivity方法 
         */jobDetail.setTargetMethod("marketingActivity"); 
        returnjobDetail;  
    } 
      
    /*** Details:配置定时任务的触发器,也就是什么时候触发执行定时任务 
     */@Bean(name = "marketingActivityJobTrigger")  
    publicCronTriggerFactoryBean cronJobTrigger(MethodInvokingJobDetailFactoryBean jobDetail) {  
        CronTriggerFactoryBean tigger = newCronTriggerFactoryBean();  
        tigger.setJobDetail(jobDetail.getObject());  
        tigger.setCronExpression("0 0 1 * * ?");//初始时的cron表达式 ,每天1点执行
        tigger.setName("marketing_activity");//trigger的name  
        returntigger;  
  
    }  
  
    /*** Details:定义quartz调度工厂 
     */@Bean(name = "marketingActivityScheduler")  
    publicSchedulerFactoryBean schedulerFactory(Trigger cronJobTrigger) {  
        SchedulerFactoryBean bean = newSchedulerFactoryBean();  
        //用于quartz集群,QuartzScheduler 启动时更新己存在的Job  
        bean.setOverwriteExistingJobs(true);  
        //延时启动,应用启动1秒后  
        bean.setStartupDelay(1);  
        //注册触发器  
bean.setTriggers(cronJobTrigger);  
        returnbean;  
    }  
}
View Code

3、定时查库,并更新任务

packagecloud.app.prod.home.quartz.mem;

importjavax.annotation.Resource;

importorg.quartz.CronScheduleBuilder;
importorg.quartz.CronTrigger;
importorg.quartz.JobDetail;
importorg.quartz.Scheduler;
importorg.quartz.SchedulerException;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.scheduling.annotation.EnableScheduling;
importorg.springframework.scheduling.annotation.Scheduled;
importorg.springframework.stereotype.Component;

importcloud.app.prod.home.common.FailException;
importcloud.app.prod.home.mem.vo.MarketingActivitiesVO;
importcloud.app.prod.home.utils.DSHUtils;

/*** Author : YongBo Xie </br>
 * File Name: ScheduleRefreshDatabase.java </br>
 * Created Date: 2018年3月31日 下午3:58:08 </br>
 * Modified Date: 2018年3月31日 下午3:58:08 </br>
 * Version: 1.0 </br>
*/@Configuration  
@EnableScheduling  
@Component
public classScheduleRefreshCron {

    @Resource(name = "marketingActivityJobDetail")  
    privateJobDetail jobDetail;  
  
    @Resource(name = "marketingActivityJobTrigger")  
    privateCronTrigger cronTrigger;  
  
    @Resource(name = "marketingActivityScheduler")  
    privateScheduler scheduler;  
  
    @Scheduled(fixedRate = 5000) //每隔5s查库,并根据查询结果决定是否重新设置定时任务
//@Scheduled(cron = "0 0 1 * * ?")
    public void scheduleUpdateCronTrigger() throwsSchedulerException, FailException {  
        CronTrigger trigger =(CronTrigger) scheduler.getTrigger(cronTrigger.getKey());  
        String currentCron = trigger.getCronExpression();//当前Trigger使用的  
        String searchCron = "0 41 10 ? * *";//从数据库查询出来的  
System.out.println(currentCron);  
        System.out.println(searchCron);  
        
        //如果当前使用的cron表达式和从数据库中查询出来的cron表达式一致,则不刷新任务
        if (!currentCron.equals(searchCron)) {  
            MarketingActivitiesVO marketingActivitiesVO = newMarketingActivitiesVO();
            marketingActivitiesVO.setId(DSHUtils.generateUUID());
            
            //表达式调度构建器  
            CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(searchCron);  
            //按新的cronExpression表达式重新构建trigger  
            trigger =(CronTrigger) scheduler.getTrigger(cronTrigger.getKey());  
            trigger =trigger.getTriggerBuilder().withIdentity(cronTrigger.getKey())  
                    .withSchedule(scheduleBuilder).build();  
            //按新的trigger重新设置job执行  
scheduler.rescheduleJob(cronTrigger.getKey(), trigger);  
            currentCron =searchCron;  
        }  
    } 
}
View Code

二、可传参任务

在Spring Boot中使用Quartz时,如果job涉及到调用其他自定义方法,需要通过定义Job Factory实现自动注入

传参关键代码:

1)、接收参数

@Override
    protected void executeInternal(JobExecutionContext context) throwsJobExecutionException {
        JobDataMap dataMap =context.getJobDetail().getJobDataMap();
        MarketingActivitiesVO marketingActivitiesVO = (MarketingActivitiesVO) dataMap.get("marketingActivitiesVO");
    }
View Code

2)、传入参数

//创建一项作业
            JobDetail job = JobBuilder.newJob(ScheduleTask.class)  
                    .withIdentity("marketingActivityJob", "marketingActivityGroup")  
                    .build();  
            
            //设置参数
            MarketingActivitiesVO marketingActivitiesVO = newMarketingActivitiesVO();
            marketingActivitiesVO.setId(DSHUtils.generateUUID());
            job.getJobDataMap().put("marketingActivitiesVO", marketingActivitiesVO);
View Code

1、自定义MyJobFactory类

packagecloud.app.prod.home.quartz;

importorg.quartz.spi.TriggerFiredBundle;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.config.AutowireCapableBeanFactory;
importorg.springframework.scheduling.quartz.AdaptableJobFactory;
importorg.springframework.stereotype.Component;

/*** Author : YongBo Xie </br>
 * File Name: MyJobFactory.java </br>
 * Created Date: 2018年4月2日 下午3:27:30 </br>
 * Modified Date: 2018年4月2日 下午3:27:30 </br>
 * Version: 1.0 </br>
*/@Component
public class MyJobFactory extendsAdaptableJobFactory {
    
    @Autowired
    privateAutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throwsException {
        //调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        //进行注入
capableBeanFactory.autowireBean(jobInstance);
        returnjobInstance;
    }
}
View Code

2、配置SchedulerFactoryBean

packagecloud.app.prod.home.quartz;

importjava.io.IOException;
importjava.util.Properties;

importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.config.PropertiesFactoryBean;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.core.io.ClassPathResource;
importorg.springframework.scheduling.annotation.EnableScheduling;
importorg.springframework.scheduling.quartz.SchedulerFactoryBean;

importcloud.app.prod.home.quartz.MyJobFactory;

/*** Author : YongBo Xie </br>
 * File Name: QuartzConfigration.java </br>
 * Created Date: 2018年3月31日 下午3:42:04 </br>
 * Modified Date: 2018年3月31日 下午3:42:04 </br>
 * Version: 1.0 </br>
*/@Configuration
@EnableScheduling
public classQuartzConfigration {
    
    @Autowired
    privateMyJobFactory myJobFactory; 
    
    @Bean 
    public SchedulerFactoryBean schedulerFactoryBean() throwsIOException {
        SchedulerFactoryBean factory = newSchedulerFactoryBean();

        //用于quartz集群,QuartzScheduler 启动时更新己存在的Job
        factory.setOverwriteExistingJobs(true);
        
        //延时启动,应用启动1秒后  
//factory.setStartupDelay(1);

        //加载quartz数据源配置
//factory.setQuartzProperties(quartzProperties()); 

        //自定义Job Factory,用于Spring注入
factory.setJobFactory(myJobFactory);

        returnfactory;
    }
    
    /*** 加载quartz数据源配置
     * 
     * @return* @throwsIOException
     */@Bean
    public Properties quartzProperties() throwsIOException {
        PropertiesFactoryBean propertiesFactoryBean = newPropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));
        propertiesFactoryBean.afterPropertiesSet();
        returnpropertiesFactoryBean.getObject();
    }
}
View Code

3、执行任务类

packagecloud.app.prod.home.quartz.mem;

importorg.apache.log4j.Logger;
importorg.quartz.DisallowConcurrentExecution;
importorg.quartz.JobDataMap;
importorg.quartz.JobExecutionContext;
importorg.quartz.JobExecutionException;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.scheduling.annotation.EnableScheduling;
importorg.springframework.scheduling.quartz.QuartzJobBean;
importorg.springframework.stereotype.Component;

importcloud.app.prod.home.common.FailException;
importcloud.app.prod.home.mem.vo.MarketingActivitiesVO;
importcloud.app.prod.home.rabbitmq.mem.MarketingActivitieRabbitMqSender;

/*** Author : YongBo Xie </br>
 * File Name: ScheduleTask.java </br>
 * Created Date: 2018年3月31日 下午3:37:43 </br>
 * Modified Date: 2018年3月31日 下午3:37:43 </br>
 * Version: 1.0 </br>
*/@Configuration  
@Component //此注解必加  
@EnableScheduling //此注解必加
@DisallowConcurrentExecution //任务同步
public class ScheduleTask extendsQuartzJobBean {
    
    private static Logger logger = Logger.getLogger(ScheduleTask.class);
    @Autowired
    privateMarketingActivitieRabbitMqSender marketingActivitieRabbitMqSender;

    @Override
    protected void executeInternal(JobExecutionContext context) throwsJobExecutionException {
        logger.info("execute activity");
        JobDataMap dataMap =context.getJobDetail().getJobDataMap();
        MarketingActivitiesVO marketingActivitiesVO = (MarketingActivitiesVO) dataMap.get("marketingActivitiesVO");
        logger.info("marketingActivitiesVO.id: " +marketingActivitiesVO.getId());
        try{
            logger.info("marketingActivitieRabbitMqSender: " +marketingActivitieRabbitMqSender);
            marketingActivitieRabbitMqSender.sendRabbitmqDirect(marketingActivitiesVO);
        } catch(FailException e) {
            e.printStackTrace();
        }
    }

}
View Code

4、设置任务类

packagecloud.app.prod.home.quartz.mem;

importjava.util.Date;

importorg.apache.log4j.Logger;
importorg.quartz.CronScheduleBuilder;
importorg.quartz.CronTrigger;
importorg.quartz.DateBuilder;
importorg.quartz.JobBuilder;
importorg.quartz.JobDetail;
importorg.quartz.Scheduler;
importorg.quartz.SchedulerException;
importorg.quartz.TriggerBuilder;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.scheduling.annotation.EnableScheduling;
importorg.springframework.scheduling.annotation.Scheduled;
importorg.springframework.scheduling.quartz.SchedulerFactoryBean;
importorg.springframework.stereotype.Component;

importcloud.app.prod.home.common.FailException;
importcloud.app.prod.home.mem.vo.MarketingActivitiesVO;
importcloud.app.prod.home.utils.DSHUtils;

/*** Author : YongBo Xie </br>
 * Project Name: DSH-SCRM </br>
 * Created Date: 2018年3月31日 下午3:58:08 </br>
 * Modified Date: 2018年3月31日 下午3:58:08 </br>
 * Version: 1.0 </br>
*/@Configuration  
@EnableScheduling  
@Component
public classScheduleRefreshCron {
    
    private static Logger logger = Logger.getLogger(ScheduleRefreshCron.class);
    
    @Autowired
    privateSchedulerFactoryBean schedulerFactoryBean;
  
    @Scheduled(fixedRate = 5000) //每隔5s查库
//@Scheduled(cron = "0 0 1 * * ?")
    public void scheduleUpdateCronTrigger() throwsFailException, SchedulerException {  
        try{              
            logger.info("----- scheduling job --------");
            
            String searchCron = "*/5 * * * * ?";//从数据库查询出来的 
            
            //获取一个调度器
//SchedulerFactory factory = new StdSchedulerFactory();
//Scheduler scheduler = factory.getScheduler();  
            Scheduler scheduler =schedulerFactoryBean.getScheduler();
            
            //创建一项作业
            JobDetail job = JobBuilder.newJob(ScheduleTask.class)  
                    .withIdentity("marketingActivityJob", "marketingActivityGroup")  
                    .build();  
            
            //设置参数
            MarketingActivitiesVO marketingActivitiesVO = newMarketingActivitiesVO();
            marketingActivitiesVO.setId(DSHUtils.generateUUID());
            job.getJobDataMap().put("marketingActivitiesVO", marketingActivitiesVO);
            
            //作业的执行时间(当前时间的下一分钟)
            Date runTime = DateBuilder.evenMinuteDate(newDate());
              
            //创建一个触发器
            CronTrigger trigger =(CronTrigger)TriggerBuilder.newTrigger()  
                    .withIdentity("marketingActivityTrigger", "marketingActivityGroup")  
                    .startAt(runTime)  //该触发器将在runTime时执行作业
                    .endAt(new Date(System.currentTimeMillis()+5*1000+60*1000)) //该触发器将在runTime时结束作业 
                    .withSchedule(CronScheduleBuilder.cronSchedule(searchCron))  //具体执行时间
.build(); 
            
            //告诉调度器使用该触发器来安排作业
scheduler.scheduleJob(job, trigger); 
            //启动调度器
scheduler.start();  
            logger.info("------ started scheduler -------");
            
            logger.info("------ waiting 2 minutes ------");              
            Thread.sleep(2*60*1000);  
            
            logger.info("------- shutting down ------");
            //关闭调度器
            scheduler.shutdown(true);  
            logger.info("------- shutdown complete -------");
        }catch(Exception e){  
            logger.error(DSHUtils.formatException(e));
            throw newFailException(e.getMessage());
        }  
    } 
}
View Code

免责声明:文章转载自《springboot-quartz普通任务与可传参任务》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇jquery.validate.js的Validate表单验证Java如何连接Access数据库(两种方式实例代码)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[原创]Spring JdbcTemplate 使用总结与经验分享

引言 近期开发的几个项目,均是基于Spring boot框架的web后端项目,使用JdbcTemplate执行数据库操作,实际开发过程中,掌握了一些有效的开发经验,踩过一些坑,在此做个记录及总结,与各位读者分享。 欢迎留言与我交流。 正确使用JdbcTemplate执行数据库操作 1、Bean声明 新增类型DatabaseConfiguration,添加注...

springMVC ——Controller配置方式

一.手动配置方式(开发中主要用注解方式,可以直接看标题二:注解方式)1.web.xml中DispatcherServlet控制器的的配置 SpringMVC也是一种基于请求驱动的WEB框架,并且使用了前端控制器的设计模式。前端控制器就是DispatcherServlet控制器,只要满足web.xml文件中的【url-pattern】的规则,这个请求就会交给...

java 字符串转日期格式

/*** 字符串转日期格式 * */ public staticDate date(String date_str) { try{ Calendar zcal = Calendar.getInstance(); Timestamp timestampnow = new...

springboot启动报错

springboot启动报错信息 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of resource dependencies failed; nested excepti...

mybatis的知识点总结

1.接口绑定:两种方法,基于注解或者基于xml文档mapper,但要注意mapper的namespace要与接口路径完全一致。 2.orm格式转换:通过设置resultMap和ResultType,将数据库中的记录转换为代码的bean对象。得到list或者对象。 3.通过parameterType接收参数,进行动态sql生成。运用ognl表达式 4.走缓存...

面试官说“一开始工资不会给你太高,你可以接受吗?” 怎么怼回去??

面试官:一开始工资不会给你太高,你可以接受吗? 程序员:我一开始工作表现不会太好,你可以接受吗? 面试官:emmmmmm 面试官:“你简历上写着说你心算速度很快,那我问问你,十九乘以十七是多少?” 程序员脱口而出:“三十六!” 面试官:“这也差太远了吧。” 程序员:“但是很快没错吧。” ----我是分割线,重点看下面---- draft_job应用...