Quartz集成springMVC 的方案二(持久化任務、集羣和分佈式)

阿里的面試官問,若是如今不少調度任務,如何優化,可使用調度池參考:ScheduledExecutor,html

參考:Java 幾種調度任務的Timer、ScheduledExecutor、 開源工具包 Quartz、開源工具包 JCronTabjava

 

言歸正傳:mysql

Quartz是一個開放源碼項目,專一於任務調度器,提供了極爲普遍的特性如持久化任務,集羣和分佈式任務等。 Quartz核心是調度器,還採用多線程管理。 面試

1.持久化任務:當應用程序中止運行時,全部調度信息不被丟失,當你從新啓動時,調度信息還存在,這就是持久化任務。 spring

2.集羣和分佈式處理:當在集羣環境下,當有配置Quartz的多個客戶端時(節點),採用Quartz的集羣和分佈式處理時,咱們要了解幾點好處sql

 1) 一個節點沒法完成的任務,會被集羣中擁有相同的任務的節點取代執行。數據庫

2) Quartz調度是經過觸發器的類別來識別不一樣的任務,在不一樣的節點定義相同的觸發器的類別,這樣在集羣下能穩定的運行,一個節點沒法完成的任務,會被集羣中擁有相同的任務的節點取代執行。tomcat

3)分佈式 體如今 當相同的任務定時在一個時間點,在那個時間點,不會被兩個節點同時執行。 多線程

 Quartz的 Task(11 張表)實例化採用數據庫存儲,基於數據庫引擎及 High-Available 的策略(集羣的一種策略)自動協調每一個節點的 Quartz。  oracle

delete from qrtz_fired_triggers;  
delete from qrtz_simple_triggers;  
delete from qrtz_simprop_triggers;  
delete from qrtz_cron_triggers;  
delete from qrtz_blob_triggers;  
delete from qrtz_triggers;  
delete from qrtz_job_details;  
delete from qrtz_calendars;  
delete from qrtz_paused_trigger_grps;  
delete from qrtz_locks;  
delete from qrtz_scheduler_state;  
   
   
   
CREATE TABLE qrtz_job_details  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    JOB_NAME  VARCHAR2(200) NOT NULL,  
    JOB_GROUP VARCHAR2(200) NOT NULL,  
    DESCRIPTION VARCHAR2(250) NULL,  
    JOB_CLASS_NAME   VARCHAR2(250) NOT NULL,   
    IS_DURABLE VARCHAR2(1) NOT NULL,  
    IS_NONCONCURRENT VARCHAR2(1) NOT NULL,  
    IS_UPDATE_DATA VARCHAR2(1) NOT NULL,  
    REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,  
    JOB_DATA BLOB NULL,  
    CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)  
);  
CREATE TABLE qrtz_triggers  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    JOB_NAME  VARCHAR2(200) NOT NULL,   
    JOB_GROUP VARCHAR2(200) NOT NULL,  
    DESCRIPTION VARCHAR2(250) NULL,  
    NEXT_FIRE_TIME NUMBER(13) NULL,  
    PREV_FIRE_TIME NUMBER(13) NULL,  
    PRIORITY NUMBER(13) NULL,  
    TRIGGER_STATE VARCHAR2(16) NOT NULL,  
    TRIGGER_TYPE VARCHAR2(8) NOT NULL,  
    START_TIME NUMBER(13) NOT NULL,  
    END_TIME NUMBER(13) NULL,  
    CALENDAR_NAME VARCHAR2(200) NULL,  
    MISFIRE_INSTR NUMBER(2) NULL,  
    JOB_DATA BLOB NULL,  
    CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)   
      REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)   
);  
CREATE TABLE qrtz_simple_triggers  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    REPEAT_COUNT NUMBER(7) NOT NULL,  
    REPEAT_INTERVAL NUMBER(12) NOT NULL,  
    TIMES_TRIGGERED NUMBER(10) NOT NULL,  
    CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
);  
CREATE TABLE qrtz_cron_triggers  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    CRON_EXPRESSION VARCHAR2(120) NOT NULL,  
    TIME_ZONE_ID VARCHAR2(80),  
    CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
);  
CREATE TABLE qrtz_simprop_triggers  
  (            
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    STR_PROP_1 VARCHAR2(512) NULL,  
    STR_PROP_2 VARCHAR2(512) NULL,  
    STR_PROP_3 VARCHAR2(512) NULL,  
    INT_PROP_1 NUMBER(10) NULL,  
    INT_PROP_2 NUMBER(10) NULL,  
    LONG_PROP_1 NUMBER(13) NULL,  
    LONG_PROP_2 NUMBER(13) NULL,  
    DEC_PROP_1 NUMERIC(13,4) NULL,  
    DEC_PROP_2 NUMERIC(13,4) NULL,  
    BOOL_PROP_1 VARCHAR2(1) NULL,  
    BOOL_PROP_2 VARCHAR2(1) NULL,  
    CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
);  
CREATE TABLE qrtz_blob_triggers  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    BLOB_DATA BLOB NULL,  
    CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
    CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
);  
CREATE TABLE qrtz_calendars  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    CALENDAR_NAME  VARCHAR2(200) NOT NULL,   
    CALENDAR BLOB NOT NULL,  
    CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)  
);  
CREATE TABLE qrtz_paused_trigger_grps  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    TRIGGER_GROUP  VARCHAR2(200) NOT NULL,   
    CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)  
);  
CREATE TABLE qrtz_fired_triggers   
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    ENTRY_ID VARCHAR2(95) NOT NULL,  
    TRIGGER_NAME VARCHAR2(200) NOT NULL,  
    TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
    INSTANCE_NAME VARCHAR2(200) NOT NULL,  
    FIRED_TIME NUMBER(13) NOT NULL,  
    SCHED_TIME NUMBER(13) NOT NULL,  
    PRIORITY NUMBER(13) NOT NULL,  
    STATE VARCHAR2(16) NOT NULL,  
    JOB_NAME VARCHAR2(200) NULL,  
    JOB_GROUP VARCHAR2(200) NULL,  
    IS_NONCONCURRENT VARCHAR2(1) NULL,  
    REQUESTS_RECOVERY VARCHAR2(1) NULL,  
    CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)  
);  
CREATE TABLE qrtz_scheduler_state   
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    INSTANCE_NAME VARCHAR2(200) NOT NULL,  
    LAST_CHECKIN_TIME NUMBER(13) NOT NULL,  
    CHECKIN_INTERVAL NUMBER(13) NOT NULL,  
    CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)  
);  
CREATE TABLE qrtz_locks  
  (  
    SCHED_NAME VARCHAR2(120) NOT NULL,  
    LOCK_NAME  VARCHAR2(40) NOT NULL,   
    CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)  
);  
   
create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);  
create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);  
   
create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);  
create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);  
create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);  
create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);  
create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);  
create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);  
create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);  
create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);  
create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);  
   
create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);  
create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);  
create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);  
create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);  
create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
View Code

 

我在新建一個張表,爲了方便頁面能對每一個任務進行管理,能對具體某個任務設置開始時間、結束時間、執行的方法、刪除等, 以下面圖所示: 

 

 在這邊能夠管理開始時間和結束時間和cronExpression值,方便管理對應表的設計: 

  

表都設計好了,整理Quartz集成springMVC的具體的實現。

spring的@component 的說明:@component (把普通pojo實例化到spring容器中,至關於配置文件中的<bean id="" class=""/>) 

1.舉例兩個任務具體實現功能,列如quartzJobA和quartzJobB任務要作什麼,新建了兩個類和方法。  

import org.springframework.stereotype.Component;    
@Component("quartzJobA")  
public class Data2ServiceImpl {    
    public void run() {  
        System.out.println("=============Data2ServiceImpl=========");            
    }  
}    
@Component("quartzJobB")  
public class DataServiceImpl {      
    public void test() {  
        System.out.println("=============DataServiceImpl=========");            
    }    
}  

  2.Quartz 調度任務所需的配置文件 quartz-job.properties

  

#Main Scheduler Settings  
org.quartz.scheduler.instanceName=quartzScheduler    
org.quartz.scheduler.instanceId=AUTO  
org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true  
org.quartz.scheduler.skipUpdateCheck=true  
org.quartz.scheduler.batchTriggerAcquisitionMaxCount=100  
  
org.quartz.threadPool.threadCount=10  
  
#Configure JDBC-JobStoreTX  
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate  
org.quartz.jobStore.dataSource=myDS  
org.quartz.jobStore.tablePrefix=QRTZ_  
org.quartz.jobStore.isClustered=true  
org.quartz.jobStore.acquireTriggersWithinLock=true  
org.quartz.jobStore.clusterCheckinInterval = 30000  
  
#Configure DataSources  
org.quartz.dataSource.myDS.driver=com.alibaba.druid.proxy.DruidDriver  
org.quartz.dataSource.myDS.URL=jdbc:wrap-jdbc:filters=default:name=dragoon:jdbc:oracle:thin:@127.0.0.1:1521:test  
org.quartz.dataSource.myDS.user=  
org.quartz.dataSource.myDS.password=  
org.quartz.dataSource.myDS.maxConnections=5  
org.quartz.dataSource.myDS.validationQuery=select 1 from dual  

org.quartz.scheduler.instanceName 屬性可爲任何值,用在 JDBC JobStore 中來惟一標識實例,可是全部集羣節點中必須相同 

org.quartz.jobStore.class屬性爲 JobStoreTX,將任務持久化到數據中。由於集羣中節點依賴於數據庫來傳播 Scheduler 實例的狀態,你只能在使用 JDBC JobStore 時應用 Quartz 集羣。這意味着你必須使用 JobStoreTX 或是 JobStoreCMT 做爲 Job 存儲;你不能在集羣中使用 RAMJobStore

3.實現任務的建立和管理

 

@Component("schedulerHelper")  
public class SchedulerHelper  
{  
  
    private static final String CONFIG_FILE="quartz-job.properties";  
    private static final String IDENTITY_JOB_PREFIX="job_";  
    private static final String IDENTITY_TRIGGER_PREFIX="trigger_";  
          
       @Autowired  
    private JobService jobService;//jobService 這個服務是實現管理任務的頁面的服務實現  
    private Scheduler scheduler;  
      
      
  
    @Autowired  
    private StartJobSchedulerListener startJobSchedulerListener;//實現本身的Scheduler監聽器,程序啓動時,任務沒建立時就建立  
  
      
      
      
       /** 
     * tomcat一啓動時,類實例化時就執行 
     */  
    public void  init()  
    {  
        try{  
               
             // 建立一個定時器工廠  
            StdSchedulerFactory sf = new StdSchedulerFactory();  
                        //初始化quartz-job.properties配置文件  
            sf.initialize(Thread.currentThread().getContextClassLoader().getResource(CONFIG_FILE).getFile());  
            scheduler = sf.getScheduler();  
            //把jobService放到scheduler上下文,job執行是能夠獲取並訪問。  
            scheduler.getContext().put(SCHEDULER_KEY_JOBSERVICE,jobService);  
            startJobSchedulerListener.setSchedulerHelper(this);  
                         //設置本身的監聽器  
            scheduler.getListenerManager().addSchedulerListener(startJobSchedulerListener);  
                       // 啓動定時器  
            scheduler.start();  
            logger.info("====================job scheduler start");           
        }catch(SchedulerException e){  
            logger.error("error",e);              
        }  
          
    }  
      
          
         /** 
     * 根據jobentity建立並開始任務 
     */  
   public boolean createAndStartJob(JobEntity job)  
    {  
        JobDetail jobDetail=generateJobDetail(job);  
        Trigger trigger=generateTriggerBuilder(job).build();  
          
        try {  
            scheduler.scheduleJob(jobDetail, trigger);  
            return true;  
        } catch (SchedulerException e) {  
            logger.error("scheduler.scheduleJob",e);  
            return false;  
        }  
    }  
        /** 
     * 清除 
     */  
    public void clearAllScheduler()  
    {  
        try {  
            scheduler.clear();  
        } catch (SchedulerException e) {  
            logger.error("clearAllScheduler",e);  
        }  
    }  
      
          
         /** 
     * 根據jobId和類型刪除 
     */  
    public boolean removeJob(Long jobId,String jobType)   
    {  
        try {  
            scheduler.deleteJob(getJobKey(jobId,jobType));  
            return true;  
        } catch (SchedulerException e) {  
            logger.error("removeJob",e);  
            return false;  
        }         
    }  
          
         /** 
     * 暫停任務 
     */  
    public boolean pauseJob(Long jobId,String jobType)  
    {  
        try {  
            scheduler.pauseJob(getJobKey(jobId,jobType));  
            return true;  
        } catch (SchedulerException e) {  
            logger.error("resumeJob",e);  
            return false;  
        }  
    }  
       
        /** 
     * 立刻只執行一次任務 
     */  
    public boolean executeOneceJob(Long jobId,String jobType)  
    {  
        try {  
            Calendar end=Calendar.getInstance();              
            TriggerBuilder<SimpleTrigger> simpleTriggerBuilder=TriggerBuilder.newTrigger()  
                                                .withIdentity(getTriggerKey(jobId,jobType))  
                                                .forJob(getJobKey(jobId,jobType))  
                                                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2));  
            end.add(Calendar.SECOND, 2);  
            simpleTriggerBuilder.startAt(end.getTime());  
            end.add(Calendar.SECOND, 5);  
            simpleTriggerBuilder.endAt(end.getTime());  
            JobEntity job=jobService.getJobById(jobId);  
              
            JobDataMap jobDataMap=new JobDataMap();  
            jobDataMap.put("jobEntity", job);  
            simpleTriggerBuilder.usingJobData(jobDataMap);  
            Trigger trigger=simpleTriggerBuilder.build();  
              
            scheduler.scheduleJob(trigger);  
            return true;  
        } catch (SchedulerException e) {  
            logger.error("executeOneceJob",e);  
            return false;  
        }  
    }  
        /** 
     * 啓動一些scheduler裏沒有的active的jobDetail 
     */  
    public void createActiveJobFromDB() throws SchedulerException  
    {  
        List<JobEntity> jobs=jobService.getActiveJob();  
        for(JobEntity job:jobs)  
        {  
            if(scheduler.getJobDetail(getJobKey(job))==null)  
                createAndStartJob(job);  
        }  
    }  
          
       /** 
     * 得到任務的jobKey 
     */  
    public static JobKey getJobKey(Long jobId,String jobType)  
    {  
        return new JobKey(IDENTITY_JOB_PREFIX+jobId,IDENTITY_JOB_PREFIX+jobType);  
    }  
      
      /** 
     * 得到任務的jobKey 
     */  
  
    public static JobKey getJobKey(JobEntity job)  
    {  
        return new JobKey(IDENTITY_JOB_PREFIX+job.getJobId(),IDENTITY_JOB_PREFIX+job.getJobType());  
    }  
      
    /** 
     * 得到trigger的triggerkey 
     */  
    public static TriggerKey getTriggerKey(JobEntity job)  
    {  
        return new TriggerKey(IDENTITY_TRIGGER_PREFIX+job.getJobId()+"_"+System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX+job.getJobType());  
    }  
      
  
        /** 
     * 得到trigger的triggerkey 
     */  
    public static TriggerKey getTriggerKey(Long jobId,String jobType)  
    {  
        return new TriggerKey(IDENTITY_TRIGGER_PREFIX+jobId+"_"+System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX+jobType);  
    }  
      
    public static JobDetail generateJobDetail(JobEntity job)  
    {  
        JobDataMap jobDataMap=new JobDataMap();  
        jobDataMap.put("jobEntity", job);  
        Class<? extends Job> clazz=null;  
         clazz=BeanJob.class;  
        return JobBuilder.newJob(clazz)  
                        .withIdentity(getJobKey(job))  
                        .usingJobData(jobDataMap)  
                        .requestRecovery(true).storeDurably(true)  
                        .build();  
    }  
      
      
       /** 
     * 根據jobEntity得到trigger 
     */  
  
    public static TriggerBuilder<CronTrigger> generateTriggerBuilder(JobEntity job)  
    {  
        TriggerBuilder<CronTrigger> triggerBuilder= TriggerBuilder.newTrigger()  
                .withIdentity(getTriggerKey(job))  
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpr())  
                                                .withMisfireHandlingInstructionDoNothing());  
        if(job.getSyncBeginTime()!=null)  
            triggerBuilder.startAt(job.getSyncBeginTime());  
        else  
            triggerBuilder.startNow();  
          
        if(job.getSyncEndTime()!=null)  
            triggerBuilder.endAt(job.getSyncEndTime());  
      
        return triggerBuilder;  
    }  
      
    public static JobService getJobService(JobExecutionContext context)  
    {  
        try {  
            return (JobService) context.getScheduler().getContext().get(SchedulerHelper.SCHEDULER_KEY_JOBSERVICE);  
        } catch (SchedulerException e) {  
            logger.error("SchedulerHelper.getJobService",e);  
            return null;  
        }  
    }  

4.實現本身的Scheduler監聽器,程序啓動時,建立scheduler裏沒有的active的jobDetail

   

@Component(value="startJobSchedulerListener")  
public class StartJobSchedulerListener extends SchedulerListenerSupport   
{  
    private SchedulerHelper schedulerHelper;  
      
    @Override  
    public void schedulerStarted()  
    {  
        try {  
            schedulerHelper.createActiveJobFromDB();  
        } catch (SchedulerException e) {  
            logger.error("createActiveJobFromDB",e);  
        }  
    }    
    public SchedulerHelper getSchedulerHelper() {  
        return schedulerHelper;  
    }    
    public void setSchedulerHelper(SchedulerHelper schedulerHelper) {  
        this.schedulerHelper = schedulerHelper;  
    }               
} 

5.實現的是一個job實例對應一個線程並實現頁面配置對應的哪一個類和方法

 

public abstract class AbstractEdiJob implements Job   
{  
    protected JobEntity jobEntity;   
    protected static final Logger logger=LoggerFactory.getLogger(AbstractEdiJob.class);  
    private Long beginTime;  
          
    @Override  
    public void execute(JobExecutionContext context) throws JobExecutionException   
    {  
        JobService jobService=SchedulerHelper.getJobService(context);  
        preExcute(jobService,context);  
        exeucuteInternal(context);  
        postExcute(jobService,context);  
    }  
      
    abstract public void exeucuteInternal(JobExecutionContext context);  
      
    public void preExcute(JobService jobService,JobExecutionContext context)  
    {  
        beginTime=System.currentTimeMillis();  
    }  
      
    public void postExcute(JobService jobService,JobExecutionContext context)  
    {  
        //得到最新的jobEntiry  
        jobEntity=jobService.getJobById(jobEntity.getJobId());  
        if(jobEntity==null)  
        {  
            logger.warn(jobEntity.getJobId()+"job不能存在");  
            return;  
        }  
        if(context.getFireTime()!=null)  
            jobEntity.setRuntimeLast(context.getFireTime());  
        if(context.getNextFireTime()!=null)  
            jobEntity.setRuntimeNext(context.getNextFireTime());  
    /*  else 
            jobEntity.setJobStatus();*/  
        Long times=jobEntity.getRunTimes();  
        jobEntity.setRunTimes((times==null?0l:times)+1);  
        Long duration=jobEntity.getRunDuration();  
        jobEntity.setRunDuration((duration==null?0l:duration)+(System.currentTimeMillis()-beginTime));  
        jobService.updateJob(jobEntity);  
        //jobEntity這裏的改變不能改變JobDetail裏的JobEntity,由於生產的job是JobDetail的JobEntity的複製  
    }   
    public void setJobEntity(JobEntity jobEntity) {  
        this.jobEntity = jobEntity;  
    }   
}  

 

/** 
 *執行具體類中的方法 
 **/  
public class BeanJob extends AbstractEdiJob   
{  
    private static Logger logger=LoggerFactory.getLogger(BeanJob.class);  
    @Override  
    public void exeucuteInternal(JobExecutionContext context)   
    {  
        Object obj=SpringContextUtil.getBean(jobEntity.getJobObject());  
        try {  
            Method method=obj.getClass().getMethod(jobEntity.getJobMethod());  
            method.invoke(obj);  
        } catch (SecurityException e) {  
            logger.error("error",e);  
        } catch (NoSuchMethodException e) {  
            logger.error("error",e);  
        } catch (IllegalArgumentException e) {  
            logger.error("error",e);  
        } catch (IllegalAccessException e) {  
            logger.error("error",e);  
        } catch (InvocationTargetException e) {  
            logger.error("error",e);  
        }  
    }  
  
}  

 

6.新增一個任務時,數據庫就保存對應的觸發器,變成持久化任務,如圖所示:

  

    1.用StdSchedulerFactory來獲取Scheduler的實例,scheduler有啓動(start)、停止(stop)和暫停(pause)方法。
    2.JobDataMap實例,JobDataMap jobDataMap=new JobDataMap();jobDataMap.put("jobEntity", job);在同一任務的屢次執行之間傳遞數據
    3.建立JobDetail實例。JobBuilder.newJob(clazz).withIdentity(getJobKey(job)).usingJobData(jobDataMap).requestRecovery(true).storeDurably(true).build();返回JobDetail實例,newJob(clazz)是要執行特定任務的類;withIdentity(getJobKey(job))是job的任務名和組名;usingJobDatausingJobData(jobDataMap)傳輸數據;

    4.建立Trigger實例。TriggerBuilder<CronTrigger> triggerBuilder= TriggerBuilder.newTrigger()
                                                                                                 .withIdentity(getTriggerKey(job))
                                                                                     .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpr())
                      .withMisfireHandlingInstructionDoNothing());

   withIdentity有標示了觸發器的名稱和組(Quartz調度是經過觸發器的類別來識別不一樣的任務),和withSchedule標示執行的時間表達式 

    5.最後經過scheduler.scheduleJob()方法調度任務。    

 參考:Quartz集成springMVC 的方案二(持久化任務、集羣和分佈式)

相關文章
相關標籤/搜索