SpringBoot结合Quartz调用Spring服务时,如何避免注入不到Service的问题?

摘要:@ "toc" 前言 在很多刚使用quartz的小伙伴的体验中,如果说没有碰到这个问题的话,那可能就是还没有往深入的走,也或许有其他的解决方案。 然后wangwang我呢,也找了很久的资料
@ 目录前言一、先图解一下本次文件内容二、放代码....三、测试代码0、创建定时任务1、定时任务自动停止2、定时任务中参数改变策略后言 前言 在很多刚使用quartz的小伙伴的体验中,如果说没有碰到这个问题的话,那可能就是还没有往深入的走,也或许有其他的解决方案。 然后wangwang我呢,也找了很久的资料才找到的。然后跟自己的项目需求相结合就成了这个亚子。 后面会放参考博客内容的:(本次为简单参考为主,不做过多讲解) 一、先图解一下本次文件内容 二、放代码.... MyJobFactory.java package com.bj.quartz.config; import groovy.util.logging.Slf4j; import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; import org.springframework.stereotype.Component; @Component @Slf4j public class MyJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { @Autowired private transient AutowireCapableBeanFactory beanFactory; @Override public void setApplicationContext(final ApplicationContext context) { beanFactory = context.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); return job; } } QuartzConfiguration.java package com.bj.quartz.config; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import java.io.IOException; import java.util.Properties; @Configuration public class QuartzConfiguration { @Autowired private MyJobFactory myJobFactory; //创建调度器工厂 @Bean(name = "SchedulerFactory") public SchedulerFactoryBean schedulerFactoryBean(){ SchedulerFactoryBean factoryBean=new SchedulerFactoryBean(); factoryBean.setJobFactory(myJobFactory); return factoryBean; } @Bean(name="scheduler") public Scheduler scheduler(){ return schedulerFactoryBean().getScheduler(); } } 配置完这些之后,其实就可以了,你就可以通过控制scheduler去生成jobDetail,trigger之类的。并且不用担心spring管理的容器无法注入进来的问题 可能有些人说,这么就这么一点点呢,当然咯quartz的内容往往不止这一些,还有一些持久化的策略之类的,甚至可以提供搭建一个定时任务的控制平台。只不过暂时我这个就只有这些,能开机就使用的定时任务。 接下来的就是我本次需求的两个重点测试:1、定时任务自动停止,2、定时任务中参数改变策略 不需要的小伙伴也可以不看。。。。 三、测试代码 0、创建定时任务 initQuartz.java 这个是写的一个自启动的时候就编译一个定时任务规则的类 package com.bj.quartz.init; import com.bj.quartz.service.TScheduleTriggerParamService; import org.quartz.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @Component public class initQuartz implements ApplicationRunner { //job1的定时任务 @Value("${jobName1}") private String jobName; @Value("${groupName1}") private String groupName; @Value("${cron1}") private String cron; //job2的定时任务 @Value("${jobName2}") private String jobName2; @Value("${groupName2}") private String groupName2; @Value("${cron2}") private String cron2; @Autowired private Scheduler scheduler; private static final Logger logger = LoggerFactory.getLogger(initQuartz.class); @Override public void run(ApplicationArguments applicationArguments) throws Exception { logger.info("================quartz启动成功=============="); //创建job1 addQuartz(jobName,groupName,cron); //创建job2 addQuartz(jobName2,groupName2,cron2); } public void addQuartz(String jobName, String jobGroup, String cron){ try { //JobName+JobGroup=Primary Key //根据jobName和jobGroup生成TriggerKey TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup); //根据TriggerKey到Scheduler调度器中获取触发器 CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey); System.out.println("创建调度器"); //创建任务详情 JobDetail jobDetail= JobBuilder.newJob((Class<? extends Job>) Class.forName(jobName)) .withIdentity(jobName,jobGroup) .build(); //往Job任务中传递参数 JobDataMap jobDataMap = jobDetail.getJobDataMap(); //创建表达式调度器 CronScheduleBuilder cronSchedule = CronScheduleBuilder.cronSchedule(cron); //创建Trigger cronTrigger= TriggerBuilder.newTrigger() .withIdentity(jobName, jobGroup) .withSchedule(cronSchedule) .build(); //将jobDetail和Trigger注入到scheduler调度器中 scheduler.scheduleJob(jobDetail,cronTrigger); }catch (Exception e){ e.printStackTrace(); } } } 1、定时任务自动停止 任务类 Myjob1.java package com.bj.quartz.job; import com.bj.util.ControllerUtil; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @Component public class Myjob1 implements Job { @Value("${jobName1}") private String jobName; @Value("${groupName1}") private String groupName; @Value("${cron1}") private String cron; @Autowired private Scheduler scheduler; @Override public void execute(JobExecutionContext jobExecutionContext) { //任务主体 taskBody(jobExecutionContext); } /** * 任务主体 */ private void taskBody(JobExecutionContext jobExecutionContext){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //获取任务详情中的dataMap集合 JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); System.out.println("这是我的myjob1111111定时任务"+sdf.format(new Date())); System.out.println("本方法的一个参数有:"+jobDataMap.size()); System.out.println("job:"+jobDataMap.get("job")+"level"+jobDataMap.get("level")); System.out.println("-------------------------------"); String BockStartTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); long timeSize=0; try { /* * 拿当前时间和规定时间相比较 * */ timeSize = this.compareTime2(BockStartTime, "20200402172430"); } catch (ParseException e) { e.printStackTrace(); } /* * 如果大于0则代表任务该停下来 * */ if(timeSize>0){ System.err.println("stop job 任务!!!"); //调用停止定时任务的方法 this.stopQuary(jobName,groupName); } } /** * 关闭quary定时任务 */ private void stopQuary(String jobName, String groupName){ TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName); try { /* *停止触发器 * */ scheduler.pauseTrigger(triggerKey); /* *移除触发器 * */ scheduler.unscheduleJob(triggerKey); scheduler.deleteJob(JobKey.jobKey(jobName, groupName)); } catch (SchedulerException e) { e.printStackTrace(); } } /** * TODO 取两个时间的差 * @param day1 * @param day2 * @return 秒 * @throws ParseException */ public long compareTime2(String day1, String day2) throws ParseException { SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); Date rjsj = df.parse(day1); Date dksj = df.parse(day2); long stateTimeLong = rjsj.getTime(); long endTimeLong = dksj.getTime(); long day = (stateTimeLong - endTimeLong) / 1000L; return day; } } 2、定时任务中参数改变策略 Myjob2.java package com.bj.quartz.job; import com.bj.entity.TScheduleTriggerParam; import com.bj.quartz.service.TScheduleTriggerParamService; import com.bj.quartz.util.paramMap; import groovy.util.logging.Slf4j; import org.quartz.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; @Component @Slf4j public class Myjob2 implements Job { @Autowired private TScheduleTriggerParamService tScheduleTriggerParamService; @Override public void execute(JobExecutionContext jobExecutionContext) { //任务主体 taskBody(jobExecutionContext); } private void taskBody(JobExecutionContext jobExecutionContext){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //获取任务详情中的dataMap集合 JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); //更新params里面的值 List<TScheduleTriggerParam> params = tScheduleTriggerParamService.queryScheduleParamLst(1); for (TScheduleTriggerParam param : params) { jobDataMap.put(param.getName(),param.getValue()); } System.err.println("这是我的myjob定时任务"+sdf.format(new Date())); System.err.println("本方法的一个参数有:"+jobDataMap.size()); System.err.println("name:"+jobDataMap.get("name")+"score"+jobDataMap.get("score")); System.out.println("-------------------------------"); //我自己提供的一个Map值 HashMap jobMap1 = paramMap.getJobMap1(); System.out.println("自己建的map:"+jobMap1.get("hh")); } } 这个我就得唠唠嗑了,参数的设置可能有三种方式: 1、使用一个静态常量的map类,然后每次调用修改参数的service的时候同时把map类中的数据重新替换掉, 2、使用redis进行存储,如果是多集群的话, 3、每次使用job任务的时候都到数据库去查询一下参数并且更替掉。 根据自身情况来吧。。 后言 不过说实话,如果是需要深入了解的还是得看看官方文档之类的。 像w3c中的quartz。 还有我看到的比较详细的:触发器介绍 本次参考后解决问题的博客:Springboot整合quartz框架(附代码) 我是wangwang,感谢能看到这里。 欢迎在评论区进行评论。