springboot quartz 使用数据源 重启项目无法修改已有任务触发时间

1.问题如标题所说

使用springboot + quartz + cron表达式形式触发任务 + mysql jdbc 数据源
出现的问题是 重启服务时无法修改数据库已有任务的cron表达式也就是任务触发频率无法修改

2.解决方案

1.增加yml配置项

需要在yml 中添加如下语句即可

spring:
  quartz:
    overwrite-existing-jobs: true # 是否覆盖已有 Job 的配置

2. 增加处理类

在项目代码中增加如下类 本质类似都是通过修改bean的overwirteexistingjobs属性进行覆盖
看注解能知道是在bean配置后自动调用该方法修改 其实代码中如果想要手动修改定时任务应该通过scheduler.rescheduleJob就可以进行修改 但是需要获取到scheduler

@Configuration
@AutoConfigureAfter(QuartzAutoConfiguration.class)
public class QuartzSupportConfig{

    @Autowired(required = false)
    private List<Trigger> triggers ;

    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;

    @PostConstruct
    public void quartzScheduler() throws SchedulerException {
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        if (triggers != null){
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            for (Trigger trigger : triggers){
                scheduler.rescheduleJob(trigger.getKey(),trigger);
            }
        }
    }

}

3. 问题

1.尝试通过手动注入schedulerFactory 进行修改已有trigger 但是始终无法在启动服务时获取到数据库已有trigger

相关代码如下:(这个是错误代码哈 如果有大佬发现问题感谢指出)


@Configuration
public class UserSchedulerConfig {
    //这里用了两个数据源  这个使用了分片 但是定时任务使用的铍铜任务
    @Lazy
    @Resource(name = "shardingDataSource")
    DataSource shardingDataSource;

    @Primary
    @Bean
    public DataSource defaultDataSource() {
        return shardingDataSource;
    }
//    @Primary
    @Bean
    @QuartzDataSource
    @ConfigurationProperties(prefix = "spring.quartz.properties.org.quartz.datasource")
    public DataSource quartzDataSource(){
        return new HikariDataSource();
    }


 //这里是关键点    =======================应该是这里没注入对
    @Autowired
    private JobFactory jobFactory;

    @Bean(name="schedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        //factory.setQuartzProperties(quartzProperties());
        //这样当spring关闭时,会等待所有已经启动的quartz job结束后spring才能完全shutdown。
        factory.setWaitForJobsToCompleteOnShutdown(true);
        //这里是关键点    =======================应该是这里没注入对
        factory.setJobFactory(jobFactory);
        factory.setDataSource(quartzDataSource());
        //延长启动
        factory.setStartupDelay(1);
        //用于quartz集群,QuartzScheduler 启动时更新己存在的Job  这里是关键点1 但是没拿到
        //factory.setOverwriteExistingJobs(true);

        return factory;
    }

    //这个监听器可以监听到工程的启动,在工程停止再启动时可以让已有的定时任务继续进行。
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    //通过SchedulerFactoryBean获取Scheduler的实例
    @Bean(name="scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }
}

之后是 jobFactory注入那块

//=========这段代码打断点始终没进去   不知道为啥没执行
@Component
public  class JobFactory extends AdaptableJobFactory {

    @Autowired
    private AutowireCapableBeanFactory  capableBeanFactory;


    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        // 调用父类的方法
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}

之后是 任务配置类

@Configuration
public class QuartzConfig {

    private final String cron="0 0/1 * * * ? ";
    private final String jobName="cashOutJob";
	//这里注入scheduler 任务就是bean工厂生成的类
    @Autowired
    private Scheduler scheduler;

    @Bean
    public JobDetail cashOutJob() {
        return JobBuilder.newJob(CashOutJob.class).withIdentity(jobName).storeDurably().build();
    }

    @Bean
    public Trigger cashOutJobTrigger() {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName);
            //这里 原有思路就是看scheduler中是否有这个任务 如果有就更新  如果没有就创建新的
            CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerKey);
            
            if(Objects.nonNull(trigger)){
                String oldTime = trigger.getCronExpression();
                if (!oldTime.equalsIgnoreCase(cron)) {
                    // 触发器
                    TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                    // 触发器名,触发器组
                    triggerBuilder.withIdentity(jobName, null);
                    triggerBuilder.startNow();
                    // 触发器时间设定
                    triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                    // 创建Trigger对象
                    trigger = (CronTrigger) triggerBuilder.build();
                    // 方式一 :修改一个任务的触发时间
                    scheduler.rescheduleJob(triggerKey, trigger);
                }
                return trigger;
            }else{
                //cron方式,每隔1min执行一次   这里的build方法如果没有scheduler会默认生成
                return TriggerBuilder.newTrigger().forJob(cashOutJob())
                        .withIdentity("cashOutJob")
                        .withSchedule(CronScheduleBuilder.cronSchedule("* 0/1 * * * ? "))
                        .build();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            return null;
        }
    }
}

2.quartz官网文档看着好难受 想找配置相关的发现没有yml配置形式 如果有合适的链接欢迎在评论区补充

3. quartz学的不够深入 可能有理解错误的地方

4. 参考资料

官方配置相关文档
SpringBoot整合任务调度框架Quartz及持久化配置
springBoot2.x设置quartz的overwriteExistingJobs参数
记一次Quartz重复调度(任务重复执行)的问题排查
spring-boot-2.0.3之quartz集成,不是你想的那样哦!
SpringBoot2.0整合Quartz定时任务(持久化到数据库,更为简单的方式)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值