SpringBoot使用Quartz无法注入Bean的问题及解决
作者:tian_shl
这篇文章主要介绍了SpringBoot使用Quartz无法注入Bean的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
依赖
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> </dependency>
任务工厂 JobFactory
// 解决SpringBoot不能再Quartz中注入Bean的问题 @Component public class JobFactory extends AdaptableJobFactory { /** * AutowireCapableBeanFactory接口是BeanFactory的子类 * 可以连接和填充那些生命周期不被Spring管理的已存在的bean实例 */ private AutowireCapableBeanFactory factory; public JobFactory(AutowireCapableBeanFactory factory) { this.factory = factory; } /** * 创建Job实例 */ @Override protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception { // 实例化对象 Object job = super.createJobInstance(bundle); // 进行注入(Spring管理该Bean) factory.autowireBean(job); //返回对象 return job; } }
任务调度器 Scheduler
@Configuration public class QuartzConfig { private JobFactory jobFactory; public QuartzConfig(JobFactory jobFactory){ this.jobFactory = jobFactory; } /** * 配置SchedulerFactoryBean * * 将一个方法产生为Bean并交给Spring容器管理 */ @Bean public SchedulerFactoryBean schedulerFactoryBean() { // Spring提供SchedulerFactoryBean为Scheduler提供配置信息,并被Spring容器管理其生命周期 SchedulerFactoryBean factory = new SchedulerFactoryBean(); // 设置自定义Job Factory,用于Spring管理Job bean factory.setJobFactory(jobFactory); return factory; } @Bean(name = "scheduler") public Scheduler scheduler() { return schedulerFactoryBean().getScheduler(); } }
QuartzManager 工具类
@Service public class QuartzManager { private Scheduler scheduler; public QuartzManager(Scheduler scheduler){ this.scheduler = scheduler; } /** * 添加一个定时任务 * * @param jobName 任务名 * @param jobGroupName 任务组名 * @param triggerName 触发器名 * @param triggerGroupName 触发器组名 * @param jobClass 任务 * @param cron 时间设置,参考quartz说明文档 */ @SuppressWarnings({ "unchecked", "rawtypes" }) public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class jobClass, String cron, Map<String, Object> params) { try { // 任务名,任务组,任务执行类 JobDetail job = JobBuilder.newJob(jobClass).withIdentity(jobName, jobGroupName).build(); // 任务参数 job.getJobDataMap().putAll(params); // 触发器 TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger(); // 触发器名,触发器组 triggerBuilder.withIdentity(triggerName, triggerGroupName); triggerBuilder.startNow(); // 触发器时间设定 triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); // 创建Trigger对象 CronTrigger trigger = (CronTrigger) triggerBuilder.build(); // 调度容器设置JobDetail和Trigger scheduler.scheduleJob(job, trigger); // 启动 if (!scheduler.isShutdown()) { scheduler.start(); } } catch (Exception e) { throw new RuntimeException(e); } } /** * 修改一个任务的触发时间 * * @param triggerName 触发器名 * @param triggerGroupName 触发器组名 * @param cron 时间设置,参考quartz说明文档 */ public void modifyJobTime(String triggerName, String triggerGroupName, String cron) { try { TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey); if (trigger == null) { return; } String oldTime = trigger.getCronExpression(); if (!oldTime.equalsIgnoreCase(cron)) { // 触发器 TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger(); // 触发器名,触发器组 triggerBuilder.withIdentity(triggerName, triggerGroupName); triggerBuilder.startNow(); // 触发器时间设定 triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron)); // 创建Trigger对象 trigger = (CronTrigger) triggerBuilder.build(); // 方式一 :修改一个任务的触发时间 scheduler.rescheduleJob(triggerKey, trigger); } } catch (Exception e) { throw new RuntimeException(e); } } /** * 移除一个任务 * * @param jobName 任务名 * @param jobGroupName 任务组名 * @param triggerName 触发器名 * @param triggerGroupName 触发器组名 */ public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) { try { TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName); // 停止触发器 scheduler.pauseTrigger(triggerKey); // 移除触发器 scheduler.unscheduleJob(triggerKey); // 删除任务 scheduler.deleteJob(JobKey.jobKey(jobName, jobGroupName)); } catch (Exception e) { throw new RuntimeException(e); } } /** * 获取任务是否存在 * * STATE_BLOCKED 4 阻塞 * STATE_COMPLETE 2 完成 * STATE_ERROR 3 错误 * STATE_NONE -1 不存在 * STATE_NORMAL 0 正常 * STATE_PAUSED 1 暂停 * */ public Boolean notExists(String triggerName, String triggerGroupName) { try { return scheduler.getTriggerState(TriggerKey.triggerKey(triggerName, triggerGroupName)) == Trigger.TriggerState.NONE; } catch (Exception e) { throw new RuntimeException(e); } } }
举个栗子
自定义任务 Job
@Service public class SftpJob extends QuartzJobBean { // 该类必须为public修饰 // 该类必须含有空参数的构造器 @Value("${sftp.root.username}") private String username; @Value("${sftp.root.password}") private String password; @Value("${sftp.host}") private String host; @Value("${sftp.port}") private Integer port; @Autowired private SftpRepository sftpRepository; @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { // 传入的参数 JobDataMap params = context.getJobDetail().getJobDataMap(); ...业务逻辑... } }
管理任务
@Service public class SftpTask { // 任务名前缀 private final String job_prefix = "job_"; // 任务组前缀 private final String job_group_prefix = "job_group_"; // 触发器前缀 private final String trigger_prefix = "trigger_"; // 触发组前缀 private final String trigger_group_prefix = "trigger_group_"; private QuartzManager quartzManager; public SftpTask (QuartzManager quartzManager) { this.quartzManager = quartzManager; } /** * 根据配置生成cron表达式 */ private String getCron(SftpDTO dto) { // 时 Integer hour = dto.getHour(); // 分 Integer minute = dto.getMinute(); // 每周几 Integer week = dto.getWeek(); // 每月几号 Integer day = dto.getDay(); /* 执行时间 0每天,1每周,2每月 */ Integer execType = dto.getExecType(); String cron; switch (execType) { case 0: cron = String.format("0 %s %s * * ?", minute, hour); break; case 1: week = (week + 1) % 7; cron = String.format("0 %s %s ? * %s", minute, hour, week == 0 ? 7: week); break; case 2: cron = String.format("0 %s %s %s * ?", minute, hour, day); break; default: cron = "0 0 0 * * ?"; break; } return cron; } /** * 添加定时任务 */ private void addJob(SftpDTO dto) { Long id = dto.getId(); Map<String, Object> params = Maps.newHashMap(); params.put("id", id); quartzManager.addJob( job_prefix + id, job_group_prefix + id, trigger_prefix + id, trigger_group_prefix + id, SftpJob.class, getCron(etlSftpDTO), params ); } /** * 修改定时任务 */ public void modifyJob(SftpDTO dto) { Long id = dto.getId(); if (quartzManager.notExists(trigger_prefix + id, trigger_group_prefix + id)){ // 任务不存在 addJob(dto); } else { // 任务存在 quartzManager.modifyJobTime( trigger_prefix + id, trigger_group_prefix + id, getCron(dto) ); } } /** * 移除定时任务 */ public void removeJob(Long id) { quartzManager.removeJob( job_prefix + id, job_group_prefix + id, trigger_prefix + id, trigger_group_prefix + id ); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。