任务相关信息:springboot-quartz普通任务与可传参任务
一、任务实体类
packagecloud.app.prod.home.quartz; importjava.io.Serializable; importjava.util.Date; /*** Author : YongBo Xie </br> * File Name: ScheduleJob.java 任务job实体类 </br> * Created Date: 2018年4月3日 上午11:33:47 </br> * Modified Date: 2018年4月3日 上午11:33:47 </br> * Version: 1.0 </br> */ public class ScheduleJobEntity implementsSerializable { private static final long serialVersionUID = 6009097439379146309L; /**任务ID */ privateString jobId; /**任务名称 */ privateString jobName; /**任务分组 */ privateString jobGroup; /**任务运行时间表达式 */ privateString cronExpression; /**任务类(必须是Spring中定义的Bean) */ privateString targetObject; /**任务方法 */ privateString targetMethod; /**是否并发 */ private booleanconcurrent; /**触发器开始执行任务时间 */ privateDate startDate; /**触发器结束执行任务时间 */ privateDate endDate; publicString getJobId() { returnjobId; } public voidsetJobId(String jobId) { this.jobId =jobId; } publicString getJobName() { returnjobName; } public voidsetJobName(String jobName) { this.jobName =jobName; } publicString getJobGroup() { returnjobGroup; } public voidsetJobGroup(String jobGroup) { this.jobGroup =jobGroup; } publicString getCronExpression() { returncronExpression; } public voidsetCronExpression(String cronExpression) { this.cronExpression =cronExpression; } publicString getTargetObject() { returntargetObject; } public voidsetTargetObject(String targetObject) { this.targetObject =targetObject; } publicString getTargetMethod() { returntargetMethod; } public voidsetTargetMethod(String targetMethod) { this.targetMethod =targetMethod; } public booleanisConcurrent() { returnconcurrent; } public void setConcurrent(booleanconcurrent) { this.concurrent =concurrent; } publicDate getStartDate() { returnstartDate; } public voidsetStartDate(Date startDate) { this.startDate =startDate; } publicDate getEndDate() { returnendDate; } public voidsetEndDate(Date endDate) { this.endDate =endDate; } }
二、Spring应用上下文环境
packagecloud.app.prod.home.quartz; importorg.springframework.beans.BeansException; importorg.springframework.context.ApplicationContext; importorg.springframework.context.ApplicationContextAware; importorg.springframework.stereotype.Component; /*** Author : YongBo Xie </br> * File Name: SpringContextUtil.java </br> * Created Date: 2018年4月3日 上午11:27:55 </br> * Modified Date: 2018年4月3日 上午11:27:55 </br> * Version: 1.0 </br> */@Component public class SpringContextUtil implementsApplicationContextAware { //Spring应用上下文环境 private staticApplicationContext applicationContext; /*** 实现ApplicationContextAware接口的回调方法,设置上下文环境 */@Override public void setApplicationContext(ApplicationContext applicationContext) throwsBeansException { SpringContextUtil.applicationContext =applicationContext; } public staticApplicationContext getApplicationContext() { returnapplicationContext; } /*** 根据指定bean名称,获取对应的实例对象 * @paramname bean的名称 * @return* @throwsBeansException */ public static Object getBean(String name) throwsBeansException { if (applicationContext == null) { throw new RuntimeException("spring 上下文对象未初始化,无法完成bean的查找!"); } returnapplicationContext.getBean(name); } /*** 根据指定Bean类型,获取对应的实例对象 * @paramrequiredType bean的class类型 * @return* @throwsBeansException */ public static <T> T getBean(Class<T> requiredType) throwsBeansException { if (applicationContext == null) { throw new RuntimeException("spring 上下文对象未初始化,无法完成bean的查找!"); } returnapplicationContext.getBean(requiredType); } }
三、自定义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; } }
四、配置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(); } }
五、定时任务公共操作类
packagecloud.app.prod.home.quartz; importjava.util.ArrayList; importjava.util.List; importjava.util.Map; importorg.apache.log4j.Logger; importorg.quartz.CronScheduleBuilder; importorg.quartz.CronTrigger; importorg.quartz.Job; importorg.quartz.JobBuilder; importorg.quartz.JobDetail; importorg.quartz.Scheduler; importorg.quartz.TriggerBuilder; importorg.quartz.TriggerKey; importorg.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean; importcloud.app.prod.home.common.FailException; importcloud.app.prod.home.utils.DSHUtils; /*** Author : YongBo Xie </br> * File Name: QuartzUtil.java </br> * Created Date: 2018年4月3日 上午10:58:32 </br> * Modified Date: 2018年4月3日 上午10:58:32 </br> * Version: 1.0 </br> */ public classQuartzUtil { private static Logger logger = Logger.getLogger(QuartzUtil.class); public static List<String> jobNames = new ArrayList<String>(); public staticString getScheduleJobName(String jobName) { if(jobNames.contains(jobName)) { returnjobName; } return null; } /*** 创建一个定时任务,并做安排(用于继承job类的执行方法) * * @paramscheduler * @paramscheduleJob * @paramparamsMap * @paramjobClass * @throwsFailException */ public static void createSheduler(Scheduler scheduler, ScheduleJobEntity scheduleJob, Map<String, Object> paramsMap, Class<? extends Job> jobClass) throwsFailException { try{ logger.info("----- scheduling job --------"); //创建一项作业 JobDetail jobDetail =JobBuilder.newJob(jobClass) .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .build(); //设置参数 for (Map.Entry<String, Object>entry : paramsMap.entrySet()) { jobDetail.getJobDataMap().put(entry.getKey(), entry.getValue()); } //作业的执行时间(当前时间的下一分钟) //Date runTime = DateBuilder.evenMinuteDate(new Date()); //创建一个触发器 CronTrigger trigger = null; if (null != scheduleJob.getStartDate() && null !=scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .startAt(scheduleJob.getStartDate()) //该触发器开始执行作业时间 .endAt(scheduleJob.getEndDate()) //该触发器结束作业时间 .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) //具体执行时间 .build(); } else if (null != scheduleJob.getStartDate() && null ==scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .startAt(scheduleJob.getStartDate()) //该触发器开始执行作业时间 .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) //具体执行时间 .build(); } else if (null == scheduleJob.getStartDate() && null !=scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .endAt(scheduleJob.getEndDate()) //该触发器结束作业时间 .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) //具体执行时间 .build(); } else{ trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())) //具体执行时间 .build(); } //告诉调度器使用该触发器来安排作业 scheduler.scheduleJob(jobDetail, 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()); } } /*** 创建一个定时任务,并做安排(用于自定义执行方法) * * @paramscheduler * @paramscheduleJob * @paramparamsMap * @throwsFailException */ public static void createSheduler(Scheduler scheduler, ScheduleJobEntity scheduleJob, Map<String, Object> paramsMap) throwsFailException { try{ //新建一个基于Spring的管理Job类 MethodInvokingJobDetailFactoryBean methodInvJobDetailFB = newMethodInvokingJobDetailFactoryBean(); //设置Job组名称 methodInvJobDetailFB.setGroup(scheduleJob.getJobGroup()); //设置Job名称 methodInvJobDetailFB.setName(scheduleJob.getJobName()); //设置任务类 methodInvJobDetailFB.setTargetObject(SpringContextUtil.getApplicationContext().getBean(scheduleJob.getTargetObject())); //设置任务方法 methodInvJobDetailFB.setTargetMethod(scheduleJob.getTargetMethod()); //将管理Job类提交到计划管理类 methodInvJobDetailFB.afterPropertiesSet(); //并发设置 methodInvJobDetailFB.setConcurrent(scheduleJob.isConcurrent()); JobDetail jobDetail = methodInvJobDetailFB.getObject();//动态 //设置参数 for (Map.Entry<String, Object>entry : paramsMap.entrySet()) { jobDetail.getJobDataMap().put(entry.getKey(), entry.getValue()); } //jobName存入到队列 每隔一段时间就会扫描所以需要时检测 if (!QuartzUtil.jobNames.contains(scheduleJob.getJobName())) { QuartzUtil.jobNames.add(scheduleJob.getJobName()); } //表达式调度构建器 CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()); //按新的cronExpression表达式构建一个新的trigger CronTrigger trigger = null; if (null != scheduleJob.getStartDate() && null !=scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .startAt(scheduleJob.getStartDate()) //该触发器开始执行作业时间 .endAt(scheduleJob.getEndDate()) //该触发器结束作业时间 .withSchedule(scheduleBuilder) //具体执行时间 .build(); } else if (null != scheduleJob.getStartDate() && null ==scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .startAt(scheduleJob.getStartDate()) //该触发器开始执行作业时间 .withSchedule(scheduleBuilder) //具体执行时间 .build(); } else if (null == scheduleJob.getStartDate() && null !=scheduleJob.getEndDate()) { trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .endAt(scheduleJob.getEndDate()) //该触发器结束作业时间 .withSchedule(scheduleBuilder) //具体执行时间 .build(); } else{ trigger =(CronTrigger) TriggerBuilder.newTrigger() .withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()) .withSchedule(scheduleBuilder) //具体执行时间 .build(); } //暂时停止 任务都安排完之后统一启动 解决耗时任务按照顺序部署后执行紊乱的问题 //scheduler.standby(); //注入到管理类 scheduler.scheduleJob(jobDetail, trigger); logger.info(scheduleJob.getJobGroup() + "." + scheduleJob.getJobName() + "创建完毕"); } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } /*** 修改定时任务 * @paramscheduler * @paramscheduleJob * @paramtriggerKey * @paramtrigger * @throwsFailException */ public static void updateScheduler(Scheduler scheduler, ScheduleJobEntity scheduleJob, TriggerKey triggerKey, CronTrigger trigger) throwsFailException { try{ if (!trigger.getCronExpression().equalsIgnoreCase(scheduleJob.getCronExpression())) { //表达式调度构建器 CronScheduleBuilder scheduleBuilder =CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()); //按新的cronExpression表达式重新构建trigger trigger =trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build(); //按新的trigger重新设置job执行 scheduler.rescheduleJob(triggerKey, trigger); logger.info(scheduleJob.getJobGroup() + "." + scheduleJob.getJobName() + " 更新完毕,目前cron表达式为:" + scheduleJob.getCronExpression() + " concurrent: " +scheduleJob.isConcurrent()); } } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } /*** 删除定时任务 * @paramscheduler * @paramtriggerKey * @paramtrigger * @throwsFailException */ public static void deleteScheduler(Scheduler scheduler, TriggerKey triggerKey, CronTrigger trigger) throwsFailException { try{ scheduler.pauseTrigger(triggerKey);//停止触发器 scheduler.unscheduleJob(triggerKey);//移除触发器 scheduler.deleteJob(trigger.getJobKey());//删除任务 logger.info(triggerKey.getGroup() + "." + triggerKey.getName() + "删除完毕"); } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } /*** 暂停定时任务 * @paramscheduler * @paramtrigger * @throwsFailException */ public static void pauseScheduler(Scheduler scheduler, CronTrigger trigger) throwsFailException { try{ scheduler.pauseJob(trigger.getJobKey());//暂停任务 logger.info(trigger.getJobKey().getGroup() + "." + trigger.getJobKey().getName() + "暂停完毕"); } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } /*** 恢复定时任务 * @paramscheduler * @paramtrigger * @throwsFailException */ public static void resumeScheduler(Scheduler scheduler, CronTrigger trigger) throwsFailException { try{ scheduler.resumeJob(trigger.getJobKey());//恢复任务 logger.info(trigger.getJobKey().getGroup() + "." + trigger.getJobKey().getName() + "恢复完毕"); } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } /*** 立即执行定时任务 * @paramscheduler * @paramtrigger * @throwsFailException */ public static void triggerScheduler(Scheduler scheduler, CronTrigger trigger) throwsFailException { try{ scheduler.triggerJob(trigger.getJobKey());//立即执行任务 logger.info(trigger.getJobKey().getGroup() + "." + trigger.getJobKey().getName() + "立即执行完毕"); } catch(Exception e) { logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } }
六、具体任务操作类
packagecloud.app.prod.home.quartz.mem; importjava.util.HashMap; importjava.util.Map; importorg.apache.log4j.Logger; importorg.quartz.CronTrigger; importorg.quartz.DisallowConcurrentExecution; importorg.quartz.Scheduler; importorg.quartz.TriggerKey; importorg.springframework.beans.factory.annotation.Autowired; 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.quartz.QuartzUtil; importcloud.app.prod.home.quartz.ScheduleJobEntity; 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> */@Component @DisallowConcurrentExecution //任务同步 public classMarketingActivityScheduleHandle { private static Logger logger = Logger.getLogger(MarketingActivityScheduleHandle.class); @Autowired privateSchedulerFactoryBean schedulerFactoryBean; //公用Scheduler,同一个对象 //public static Scheduler scheduler = (Scheduler) SpringContextUtil.getApplicationContext().getBean("schedulerFactoryBean"); @Scheduled(fixedRate = 5000) //每隔5s查库 //@Scheduled(cron = "0 0 1 * * ?") public void scheduleRefreshCron() throwsFailException { try{ logger.info("----- scheduling job --------"); String searchCron = "*/5 * * * * ?";//从数据库查询出来的 //获取一个调度器 //SchedulerFactory factory = new StdSchedulerFactory(); //Scheduler scheduler = factory.getScheduler(); Scheduler scheduler =schedulerFactoryBean.getScheduler(); //设置参数 MarketingActivitiesVO marketingActivitiesVO = newMarketingActivitiesVO(); marketingActivitiesVO.setId(DSHUtils.generateUUID()); ScheduleJobEntity scheduleJob = newScheduleJobEntity(); scheduleJob.setJobId(marketingActivitiesVO.getId()); scheduleJob.setJobName("marketingActivity"); scheduleJob.setJobGroup("marketingActivityGroup"); scheduleJob.setCronExpression(searchCron); scheduleJob.setTargetObject("marketingActivityScheduleTask"); scheduleJob.setTargetMethod("executeInternal"); scheduleJob.setConcurrent(true); Map<String, Object> paramsMap = new HashMap<>(); paramsMap.put("marketingActivitiesVO", marketingActivitiesVO); //获取triggerKey TriggerKey triggerKey =TriggerKey.triggerKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()); //获取trigger CronTrigger trigger =(CronTrigger) scheduler.getTrigger(triggerKey); //不存在,创建一个 if (null ==trigger) { //创建一个触发器 QuartzUtil.createSheduler(scheduler, scheduleJob, paramsMap, MarketingActivityScheduleTask.class); //QuartzUtil.createSheduler(scheduler, scheduleJob, paramsMap); } else {//Trigger已存在,那么更新相应的定时设置 QuartzUtil.updateScheduler(scheduler, scheduleJob, triggerKey, trigger); //删除 QuartzUtil.deleteScheduler(scheduler, triggerKey, trigger); } }catch(Exception e){ logger.error(DSHUtils.formatException(e)); throw newFailException(e.getMessage()); } } }
七:1)、具体任务执行类(继承Job)
packagecloud.app.prod.home.quartz.mem; importorg.apache.log4j.Logger; importorg.quartz.JobDataMap; importorg.quartz.JobExecutionContext; importorg.quartz.JobExecutionException; importorg.springframework.beans.factory.annotation.Autowired; 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> */@Component //此注解必加 @EnableScheduling //此注解必加 public class MarketingActivityScheduleTask extendsQuartzJobBean { private static Logger logger = Logger.getLogger(MarketingActivityScheduleTask.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(); } } }
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"); } }