定时任务 Springboot+quartz+service层不能注入的问题
1 添加依赖
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency>
2 创建Factory(代码可照抄)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.souche.salt_common_01.config; 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 MyJobFactory extends AdaptableJobFactory { @Autowired private AutowireCapableBeanFactory capableBeanFactory; @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { // 调用父类的方法 Object jobInstance = super.createJobInstance(bundle); // 进行注入 capableBeanFactory.autowireBean(jobInstance); return jobInstance; } }
3 创建配置文件(代码可照抄)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.souche.salt_common_01.config; import org.quartz.Scheduler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.SchedulerFactoryBean; @Configuration public class QuartzConfig { @Autowired private MyJobFactory myJobFactory; @Bean public SchedulerFactoryBean schedulerFactoryBean() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setJobFactory(myJobFactory); System.out.println("myJobFactory:"+myJobFactory); return schedulerFactoryBean; } @Bean public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } }
4 创建job 定时执行此job里面的方法(你要执行的业务代码在这里面)
package com.souche.salt_common_01.service.impl; import com.souche.salt_common_01.controller.SctiptsController; import com.souche.salt_common_01.controller.TimeJobController; import com.souche.salt_common_01.entity.JobsLog; import com.souche.salt_common_01.entity.Scripts; import com.souche.salt_common_01.entity.ScriptsExample; import com.souche.salt_common_01.mapper.ScriptsMapper; import com.souche.salt_common_01.service.ClientService; import com.souche.salt_common_01.utils.IDUtils; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.Date; import java.util.List; import java.util.Map; public class SchedulerQuartzJob1 implements Job{ @Autowired private TimeJobController timeJobController; @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("开始:"+System.currentTimeMillis()); //此处可获得你要执行的名字 String JobName=arg0.getJobDetail().getKey().getName(); System.out.println("结束:"+System.currentTimeMillis()); } }
5 创建配置文件(可照抄 )
我只试用过第一个方法startJob 新建一个任务:传入任务名 ,执行时间两个参数,执行时间是cron表达式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.souche.salt_common_01.config; import java.util.Date; import com.souche.salt_common_01.service.impl.SchedulerQuartzJob1; import org.quartz.CronScheduleBuilder; import org.quartz.CronTrigger; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; /** * 任务调度处理 * @author yvan * */ @Configuration public class QuartzScheduler { // 任务调度 @Autowired private Scheduler scheduler; /** * 开始执行所有任务 * * @throws SchedulerException */ public void startJob(String jobName,String startTime) throws SchedulerException { //startJob1(scheduler,name,startTime); // 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接口的实例 // JobDetail 是具体Job实例 JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob1.class).withIdentity(jobName, "group1").build(); // 基于表达式构建触发器 // CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?"); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(startTime); // CronTrigger表达式触发器 继承于Trigger // TriggerBuilder 用于构建触发器实例 CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName, "group1") .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); scheduler.start(); } /** * 获取Job信息 * * @param name * @param group * @return * @throws SchedulerException */ public String getJobInfo(String name, String group) throws SchedulerException { TriggerKey triggerKey = new TriggerKey(name, group); CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey); return String.format("time:%s,state:%s", cronTrigger.getCronExpression(), scheduler.getTriggerState(triggerKey).name()); } /** * 修改某个任务的执行时间 * * @param name * @param group * @param time * @return * @throws SchedulerException */ public void modifyJob(String name, String group, String time) throws SchedulerException { Date date = null; System.err.println(name); System.err.println(group); TriggerKey triggerKey = new TriggerKey(name, group); CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey); String oldTime = cronTrigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(time)) { CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(time); CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(name, group) .withSchedule(cronScheduleBuilder).build(); date = scheduler.rescheduleJob(triggerKey, trigger); } // return date != null?true:false; } /** * 暂停所有任务 * * @throws SchedulerException */ public void pauseAllJob() throws SchedulerException { scheduler.pauseAll(); } /** * 暂停某个任务 * * @param name * @param group * @throws SchedulerException */ public void pauseJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if (jobDetail == null) return; scheduler.pauseJob(jobKey); } /** * 恢复所有任务 * * @throws SchedulerException */ public void resumeAllJob() throws SchedulerException { scheduler.resumeAll(); } /** * 恢复某个任务 * * @param name * @param group * @throws SchedulerException */ public void resumeJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if (jobDetail == null) return; scheduler.resumeJob(jobKey); } /** * 删除某个任务 * * @param name * @param group * @throws SchedulerException */ public void deleteJob(String name, String group) throws SchedulerException { JobKey jobKey = new JobKey(name, group); JobDetail jobDetail = scheduler.getJobDetail(jobKey); if (jobDetail == null) return; scheduler.deleteJob(jobKey); } /* private void startJob1(Scheduler scheduler,String name,String startTime) throws SchedulerException { // 通过JobBuilder构建JobDetail实例,JobDetail规定只能是实现Job接口的实例 // JobDetail 是具体Job实例 JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob1.class).withIdentity(name, "group1").build(); // 基于表达式构建触发器 CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?"); // CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(startTime); // CronTrigger表达式触发器 继承于Trigger // TriggerBuilder 用于构建触发器实例 CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(name, "group1") .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); }*/ private void startJob2(Scheduler scheduler) throws SchedulerException { JobDetail jobDetail = JobBuilder.newJob(SchedulerQuartzJob2.class).withIdentity("job2", "group2").build(); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/5 * * * ?"); CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity("job2", "group2") .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, cronTrigger); } }
6编写API
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.souche.salt_common_01.controller; import com.souche.salt_common_01.config.QuartzScheduler; import org.apache.ibatis.annotations.Delete; import org.quartz.SchedulerException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; /** * 这里并没有采用restful风格 只是简单封装了一下api * * @author yvan * */ @RestController public class QuartzApiController { @Autowired private QuartzScheduler quartzScheduler; @PostMapping("/lantu/quartz") public void startQuartzJob(String name,String startTime) { try { quartzScheduler.startJob(name,startTime); } catch (SchedulerException e) { e.printStackTrace(); } } @GetMapping("/lantu/info") public String getQuartzJob(String name, String group) { String info = null; try { info = quartzScheduler.getJobInfo(name, group); } catch (SchedulerException e) { e.printStackTrace(); } return info; } @PutMapping("/lantu/modify") public void modifyQuartzJob(String name, String startTime) { boolean flag = true; try { quartzScheduler.modifyJob(name, "group1", startTime); } catch (SchedulerException e) { e.printStackTrace(); } //return flag; } @GetMapping (value = "/lantu/pause") public void pauseQuartzJob(String name, String group) { try { quartzScheduler.pauseJob(name, group); } catch (SchedulerException e) { e.printStackTrace(); } } @GetMapping(value = "/lantu/pauseAll") public void pauseAllQuartzJob() { try { quartzScheduler.pauseAllJob(); } catch (SchedulerException e) { e.printStackTrace(); } } @DeleteMapping(value = "/lantu/delete") public void deleteJob(String name, String group) { try { quartzScheduler.deleteJob(name, group); } catch (SchedulerException e) { e.printStackTrace(); } } }
以上就是完成了一个简单的定时任务:并且解决了SchedulerQuartzJob1中不可以注入其他service 的问题。
但是一但项目重启 这些加入内存的定时任务就会丢失。解决办法如下。
7 监听器
对于监听器的使用我并不理解,我只是找了一个解决问题的办法:
每次项目启动的时候 读取数据库中自己存储任务的任务表,把任务重新添加进来。
package com.souche.salt_common_01.config; import com.souche.salt_common_01.controller.TimeJobController; import com.souche.salt_common_01.entity.TimeJobs; import com.souche.salt_common_01.entity.TimeJobsExample; import com.souche.salt_common_01.mapper.TimeJobsMapper; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SchedulerFactory; import org.quartz.impl.StdSchedulerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.event.ContextRefreshedEvent; import java.util.List; @Configuration public class ApplicationStartQuartzJobListener implements ApplicationListener<ContextRefreshedEvent>{ @Autowired private QuartzScheduler quartzScheduler; @Autowired private TimeJobsMapper timeJobsMapper; /** * 初始启动quartz */ @Override public void onApplicationEvent(ContextRefreshedEvent event) { try { //读取我的数据库 获得要执行的任务名称 和执行时间,然后添加进去 TimeJobsExample timeJobsExample=new TimeJobsExample(); timeJobsExample.or().andStatusEqualTo("running"); List<TimeJobs> timeJobs=timeJobsMapper.selectByExample(timeJobsExample); for (TimeJobs tjob:timeJobs ) { quartzScheduler.startJob(tjob.getId(),tjob.getDoTime()); } System.out.println("任务已经启动..."); } catch (Exception e) { e.printStackTrace(); } } }
以上只是我工作中暂时解决定时任务的方法:其中我用到了 添加定时任务,和删除定时任务, 其他api有待测试