spring 容器启动执行重置定时任务

需求:

对于quartz定时任务,需要自定义设置cron表达式实现修改定时任务的执行周期。

目前条件:

定时任务是在spring容器启动完毕通过@EventListener监听容器的ContextRefreshedEvent事件读取了quarz.properties文件中cron 表达式更新了定时任务触发器。
用户在修改了定时任务的cron表达式的时候,存放在了数据库中,所以需要从数据库中获取cron,然后重置触发器。这个操作希望在spring容器启动的时候做。

解决方案:

  1. 考虑使用@PostConstruct来做,这个操作在@EventListener之前,可以修改定时任务的注解,从而更新定时任务的触发器cron。
    @PostConstruct
    public void resetCron(ContextRefreshedEvent event) {
        String cron = jmsInfoService.getJmsInfo("jms.cron");
        if (cron != null) {
            try {
               //检查数据库里面有jms.cron就重新定义定时任务,替换触发器
                JmsDataSyncJob jmsDataSyncJob = new JmsDataSyncJob();
                Method sysnOldData = jmsDataSyncJob.getClass().getDeclaredMethod("sysnOldData");
                QuartzScheduled quartzScheduled = sysnOldData.getAnnotation(QuartzScheduled.class);
                InvocationHandler handler = Proxy.getInvocationHandler(quartzScheduled);
                Field f = handler.getClass().getDeclaredField("memberValues");
                f.setAccessible(true);
                Map<String, Object> memberValue = (Map<String, Object>) f.get(handler);
                memberValue.put("cron", cron);
                LogUtil.info("检查数据库里面有jms.cron设置,重新定义定时任务的cron :" + quartzScheduled.cron());
             } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }            

问题:在启动的时候如果mapper没有被完全加载完毕,会导致空指针错误,无法查询数据库,甚至无法启动spring。

  1. 考虑使用 @EventListener的方式,监听容器的ContextRefreshedEvent事件,读取数据库数据,重置定时任务触发器
  @EventListener
    public void resetCron(ContextRefreshedEvent event) {
        String cron = jmsInfoService.getJmsInfo("jms.cron");
        if (cron != null) {
            try {
                System.out.println("执行的任务 start ");
                for (int i = 0; i < quartzManageService.getCurrentlyExecutingJobs().size(); i++) {
                    System.out.println(quartzManageService.getCurrentlyExecutingJobs().get(i).getTrigger().getKey());
                }
                System.out.println("执行的任务  end ");
                String key = "jmsDataSyncJob" + "." + "sysnOldData";
                Trigger trigger = TriggerBuilder.newTrigger().withIdentity(key)
                        .withSchedule(CronScheduleBuilder.cronSchedule(cron))
                        .build();
                quartzManageService.rescheduleJob(TriggerKey.triggerKey(key), trigger);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

问题:和quartz一样都是监听容器的刷新事件,会导致执行顺序问题,如果查数据库重置的操作在quartz之前就会导致最终定时任务的cron还是读取的配置文件里面的。所以考虑监听其他的事件,保证在后面执行。

@EventListener
    public void resetCron(ContextReadyEvent event) {
        //和上面一样,也可以监听 ContextStartedEvent
    }

操作成功。

spring容器启动事件监听:
[参考连接] http://zhaoshijie.iteye.com/blog/1974682

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章