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

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